=this.size[1]||!this.properties.show||!this._video||(b.save(),b.drawImage(this._video,0,0,this.size[0],this.size[1]),b.restore())};l.prototype.onGetOutputs=function(){return[["width","number"],["height","number"],["stream_ready",e.EVENT],["stream_closed",e.EVENT],["stream_error",e.EVENT]]};
+e.registerNodeType("graphics/webcam",l)})(this);
+(function(z){function b(){this.addOutput("tex","Texture");this.addOutput("name","string");this.properties={name:"",filter:!0};this.size=[b.image_preview_size,b.image_preview_size]}function m(){this.addInput("Texture","Texture");this.properties={flipY:!1};this.size=[b.image_preview_size,b.image_preview_size]}function q(){this.addInput("Texture","Texture");this.addOutput("tex","Texture");this.addOutput("name","string");this.properties={name:"",generate_mipmaps:!1}}function p(){this.addInput("Texture",
+"Texture");this.addInput("TextureB","Texture");this.addInput("value","number");this.addOutput("Texture","Texture");this.help="pixelcode must be vec3, uvcode must be vec2, is optional
\t\tuv: tex. coords
color: texture colorB: textureB
time: scene time value: input value
For multiline you must type: result = ...
";this.properties={value:1,pixelcode:"color + colorB * value",uvcode:"",precision:b.DEFAULT};
+this.has_error=!1}function y(){this.addOutput("out","Texture");this.properties={code:"",u_value:1,u_color:[1,1,1,1],width:512,height:512,precision:b.DEFAULT};this.properties.code="//time: time in seconds\n//texSize: vec2 with res\nuniform float u_value;\nuniform vec4 u_color;\n\nvoid main() {\n vec2 uv = v_coord;\n vec3 color = vec3(0.0);\n\t//your code here\n\tcolor.xy=uv;\n\ngl_FragColor = vec4(color, 1.0);\n}\n";this._uniforms={u_value:1,u_color:vec4.create(),in_texture:0,texSize:vec2.create(),
+time:0}}function h(){this.addInput("in","Texture");this.addInput("scale","vec2");this.addInput("offset","vec2");this.addOutput("out","Texture");this.properties={offset:vec2.fromValues(0,0),scale:vec2.fromValues(1,1),precision:b.DEFAULT}}function D(){this.addInput("in","Texture");this.addInput("warp","Texture");this.addInput("factor","number");this.addOutput("out","Texture");this.properties={factor:0.01,scale:[1,1],offset:[0,0],precision:b.DEFAULT};this._uniforms={u_texture:0,u_textureB:1,u_factor:1,
+u_scale:vec2.create(),u_offset:vec2.create()}}function v(){this.addInput("Texture","Texture");this.properties={additive:!1,antialiasing:!1,filter:!0,disable_alpha:!1,gamma:1,viewport:[0,0,1,1]};this.size[0]=130}function w(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={size:0,generate_mipmaps:!1,precision:b.DEFAULT}}function B(){this.addInput("Texture","Texture");this.addOutput("","Texture");this.properties={iterations:1,generate_mipmaps:!1,precision:b.DEFAULT}}
+function l(){this.addInput("Texture","Texture");this.addOutput("tex","Texture");this.addOutput("avg","vec4");this.addOutput("lum","number");this.properties={use_previous_frame:!0,high_quality:!1};this._uniforms={u_texture:0,u_mipmap_offset:0};this._luminance=new Float32Array(4)}function e(){this.addInput("Texture","Texture");this.addOutput("min_t","Texture");this.addOutput("max_t","Texture");this.addOutput("min","vec4");this.addOutput("max","vec4");this.properties={mode:"max",use_previous_frame:!0};
+this._uniforms={u_texture:0};this._max=new Float32Array(4);this._min=new Float32Array(4);this._textures_chain=[]}function C(){this.addInput("in","Texture");this.addInput("factor","Number");this.addOutput("out","Texture");this.properties={factor:0.5};this._uniforms={u_texture:0,u_textureB:1,u_factor:this.properties.factor}}function r(){this.addInput("in","Texture");this.addOutput("avg","Texture");this.addOutput("array","Texture");this.properties={samples:64,frames_interval:1};this._uniforms={u_texture:0,
+u_textureB:1,u_samples:this.properties.samples,u_isamples:1/this.properties.samples};this.frame=0}function A(){this.addInput("Image","image");this.addOutput("","Texture");this.properties={}}function s(){this.addInput("Texture","Texture");this.addInput("LUT","Texture");this.addInput("Intensity","number");this.addOutput("","Texture");this.properties={enabled:!0,intensity:1,precision:b.DEFAULT,texture:null};s._shader||(s._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,s.pixel_shader))}function n(){this.addInput("Texture",
+"Texture");this.addOutput("R","Texture");this.addOutput("G","Texture");this.addOutput("B","Texture");this.addOutput("A","Texture");n._shader||(n._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,n.pixel_shader))}function t(){this.addInput("R","Texture");this.addInput("G","Texture");this.addInput("B","Texture");this.addInput("A","Texture");this.addOutput("Texture","Texture");this.properties={precision:b.DEFAULT,R:1,G:1,B:1,A:1};this._color=vec4.create();this._uniforms={u_textureR:0,u_textureG:1,u_textureB:2,
+u_textureA:3,u_color:this._color}}function k(){this.addOutput("Texture","Texture");this._tex_color=vec4.create();this.properties={color:vec4.create(),precision:b.DEFAULT}}function a(){this.addInput("A","color");this.addInput("B","color");this.addOutput("Texture","Texture");this.properties={angle:0,scale:1,A:[0,0,0],B:[1,1,1],texture_size:32};a._shader||(a._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,a.pixel_shader));this._uniforms={u_angle:0,u_colorA:vec3.create(),u_colorB:vec3.create()}}function c(){this.addInput("A",
+"Texture");this.addInput("B","Texture");this.addInput("Mixer","Texture");this.addOutput("Texture","Texture");this.properties={factor:0.5,size_from_biggest:!0,invert:!1,precision:b.DEFAULT};this._uniforms={u_textureA:0,u_textureB:1,u_textureMix:2,u_mix:vec4.create()}}function d(){this.addInput("Tex.","Texture");this.addOutput("Edges","Texture");this.properties={invert:!0,threshold:!1,factor:1,precision:b.DEFAULT};d._shader||(d._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,d.pixel_shader))}function g(){this.addInput("Texture",
+"Texture");this.addInput("Distance","number");this.addInput("Range","number");this.addOutput("Texture","Texture");this.properties={distance:100,range:50,only_depth:!1,high_precision:!1};this._uniforms={u_texture:0,u_distance:100,u_range:50,u_camera_planes:null}}function f(){this.addInput("Texture","Texture");this.addOutput("Texture","Texture");this.properties={precision:b.DEFAULT,invert:!1};this._uniforms={u_texture:0,u_near:0.1,u_far:1E4}}function K(){this.addInput("Texture","Texture");this.addInput("Iterations",
+"number");this.addInput("Intensity","number");this.addOutput("Blurred","Texture");this.properties={intensity:1,iterations:1,preserve_aspect:!1,scale:[1,1],precision:b.DEFAULT}}function x(){this.addInput("in","Texture");this.addInput("dirt","Texture");this.addOutput("out","Texture");this.addOutput("glow","Texture");this.properties={enabled:!0,intensity:1,persistence:0.99,iterations:16,threshold:0,scale:1,dirt_factor:0.5,precision:b.DEFAULT};this._textures=[];this._uniforms={u_intensity:1,u_texture:0,
+u_glow_texture:1,u_threshold:0,u_texel_size:vec2.create()}}function H(){this.addInput("Texture","Texture");this.addOutput("Filtered","Texture");this.properties={intensity:1,radius:5}}function I(){this.addInput("Texture","Texture");this.addOutput("Filtered","Texture");this.properties={sigma:1.4,k:1.6,p:21.7,epsilon:79,phi:0.017}}function G(){this.addOutput("Webcam","Texture");this.properties={texture_name:"",facingMode:"user"};this.boxcolor="black";this.version=0}function E(){this.addInput("in","Texture");
+this.addInput("f","number");this.addOutput("out","Texture");this.properties={enabled:!0,factor:1,precision:b.LOW};this._uniforms={u_texture:0,u_factor:1}}function u(){this.addInput("in","Texture");this.addOutput("out","Texture");this.properties={precision:b.LOW,split_channels:!1};this._values=new Uint8Array(1024);this._values.fill(255);this._curve_texture=null;this._uniforms={u_texture:0,u_curve:1,u_range:1};this._must_update=!0;this._points={RGB:[[0,0],[1,1]],R:[[0,0],[1,1]],G:[[0,0],[1,1]],B:[[0,
+0],[1,1]]};this.curve_editor=null;this.addWidget("toggle","Split Channels",!1,"split_channels");this.addWidget("combo","Channel","RGB",{values:["RGB","R","G","B"]});this.curve_offset=68;this.size=[240,160]}function M(){this.addInput("in","Texture");this.addInput("exp","number");this.addOutput("out","Texture");this.properties={exposition:1,precision:b.LOW};this._uniforms={u_texture:0,u_exposition:1}}function J(){this.addInput("in","Texture");this.addInput("avg","number,Texture");this.addOutput("out",
+"Texture");this.properties={enabled:!0,scale:1,gamma:1,average_lum:1,lum_white:1,precision:b.LOW};this._uniforms={u_texture:0,u_lumwhite2:1,u_igamma:1,u_scale:1,u_average_lum:1}}function L(){this.addOutput("out","Texture");this.properties={width:512,height:512,seed:0,persistence:0.1,octaves:8,scale:1,offset:[0,0],amplitude:1,precision:b.DEFAULT};this._key=0;this._texture=null;this._uniforms={u_persistence:0.1,u_seed:0,u_offset:vec2.create(),u_scale:1,u_viewport:vec2.create()}}function N(){this.addInput("v");
+this.addOutput("out","Texture");this.properties={code:"",width:512,height:512,clear:!0,precision:b.DEFAULT,use_html_canvas:!1};this._temp_texture=this._func=null}function O(){this.addInput("in","Texture");this.addOutput("out","Texture");this.properties={key_color:vec3.fromValues(0,1,0),threshold:0.8,slope:0.2,precision:b.DEFAULT}}function P(){this.addInput("in","texture");this.addInput("yaw","number");this.addOutput("out","texture");this.properties={yaw:0}}var F=z.LiteGraph;z.LGraphTexture=null;"undefined"!=
+typeof GL&&(LGraphCanvas.link_type_colors.Texture="#987",z.LGraphTexture=b,b.title="Texture",b.desc="Texture",b.widgets_info={name:{widget:"texture"},filter:{widget:"checkbox"}},b.loadTextureCallback=null,b.image_preview_size=256,b.PASS_THROUGH=1,b.COPY=2,b.LOW=3,b.HIGH=4,b.REUSE=5,b.DEFAULT=2,b.MODE_VALUES={"pass through":b.PASS_THROUGH,copy:b.COPY,low:b.LOW,high:b.HIGH,reuse:b.REUSE,"default":b.DEFAULT},b.getTexturesContainer=function(){return gl.textures},b.loadTexture=function(a,c){c=c||{};var d=
+a;"http://"==d.substr(0,7)&&F.proxy&&(d=F.proxy+d.substr(7));return b.getTexturesContainer()[a]=GL.Texture.fromURL(d,c)},b.getTexture=function(a){var c=this.getTexturesContainer();if(!c)throw"Cannot load texture, container of textures not found";c=c[a];return!c&&a&&":"!=a[0]?this.loadTexture(a):c},b.getTargetTexture=function(a,c,d){if(!a)throw"LGraphTexture.getTargetTexture expects a reference texture";var f=null;switch(d){case b.LOW:f=gl.UNSIGNED_BYTE;break;case b.HIGH:f=gl.HIGH_PRECISION_FORMAT;
+break;case b.REUSE:return a;default:f=a?a.type:gl.UNSIGNED_BYTE}c&&c.width==a.width&&c.height==a.height&&c.type==f||(c=new GL.Texture(a.width,a.height,{type:f,format:gl.RGBA,filter:gl.LINEAR}));return c},b.getTextureType=function(a,c){var d=c?c.type:gl.UNSIGNED_BYTE;switch(a){case b.HIGH:d=gl.HIGH_PRECISION_FORMAT;break;case b.LOW:d=gl.UNSIGNED_BYTE}return d},b.getWhiteTexture=function(){return this._white_texture?this._white_texture:this._white_texture=GL.Texture.fromMemory(1,1,[255,255,255,255],
+{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})},b.getNoiseTexture=function(){if(this._noise_texture)return this._noise_texture;for(var a=new Uint8Array(1048576),c=0;1048576>c;++c)a[c]=255*Math.random();return this._noise_texture=a=GL.Texture.fromMemory(512,512,a,{format:gl.RGBA,wrap:gl.REPEAT,filter:gl.NEAREST})},b.prototype.onDropFile=function(a,c,b){if(a){var d=null;"string"==typeof a?d=GL.Texture.fromURL(a):-1!=c.toLowerCase().indexOf(".dds")?d=GL.Texture.fromDDSInMemory(a):(a=new Blob([b]),
+a=URL.createObjectURL(a),d=GL.Texture.fromURL(a));this._drop_texture=d;this.properties.name=c}else this._drop_texture=null,this.properties.name=""},b.prototype.getExtraMenuOptions=function(a){var c=this;if(this._drop_texture)return[{content:"Clear",callback:function(){c._drop_texture=null;c.properties.name=""}}]},b.prototype.onExecute=function(){var a=null;this.isOutputConnected(1)&&(a=this.getInputData(0));!a&&this._drop_texture&&(a=this._drop_texture);!a&&this.properties.name&&(a=b.getTexture(this.properties.name));
+if(a){this._last_tex=a;!1===this.properties.filter?a.setParameter(gl.TEXTURE_MAG_FILTER,gl.NEAREST):a.setParameter(gl.TEXTURE_MAG_FILTER,gl.LINEAR);this.setOutputData(0,a);this.setOutputData(1,a.fullpath||a.filename);for(var c=2;c=this.size[1]))if(this._drop_texture&&a.webgl)a.drawImage(this._drop_texture,0,0,this.size[0],this.size[1]);else{if(this._last_preview_tex!=this._last_tex)if(a.webgl)this._canvas=this._last_tex;else{var c=b.generateLowResTexturePreview(this._last_tex);if(!c)return;this._last_preview_tex=this._last_tex;this._canvas=cloneCanvas(c)}this._canvas&&(a.save(),a.webgl||(a.translate(0,
+this.size[1]),a.scale(1,-1)),a.drawImage(this._canvas,0,0,this.size[0],this.size[1]),a.restore())}},b.generateLowResTexturePreview=function(a){if(!a)return null;var c=b.image_preview_size,d=a;if(a.format==gl.DEPTH_COMPONENT)return null;if(a.width>c||a.height>c)d=this._preview_temp_tex,this._preview_temp_tex||(this._preview_temp_tex=d=new GL.Texture(c,c,{minFilter:gl.NEAREST})),a.copyTo(d);a=this._preview_canvas;a||(this._preview_canvas=a=createCanvas(c,c));d&&d.toCanvas(a);return a},b.prototype.getResources=
+function(a){this.properties.name&&(a[this.properties.name]=GL.Texture);return a},b.prototype.onGetInputs=function(){return[["in","Texture"]]},b.prototype.onGetOutputs=function(){return[["width","number"],["height","number"],["aspect","number"]]},b.replaceCode=function(a,c){return a.replace(/\{\{[a-zA-Z0-9_]*\}\}/g,function(a){a=a.replace(/[\{\}]/g,"");return c[a]||""})},F.registerNodeType("texture/texture",b),m.title="Preview",m.desc="Show a texture in the graph canvas",m.allow_preview=!1,m.prototype.onDrawBackground=
+function(a){if(!this.flags.collapsed&&(a.webgl||m.allow_preview)){var c=this.getInputData(0);if(c){var d=null,d=!c.handle&&a.webgl?c:b.generateLowResTexturePreview(c);a.save();this.properties.flipY&&(a.translate(0,this.size[1]),a.scale(1,-1));a.drawImage(d,0,0,this.size[0],this.size[1]);a.restore()}}},F.registerNodeType("texture/preview",m),q.title="Save",q.desc="Save a texture in the repository",q.prototype.getPreviewTexture=function(){return this._texture},q.prototype.onExecute=function(){var a=
+this.getInputData(0);a&&(this.properties.generate_mipmaps&&(a.bind(0),a.setParameter(gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR),gl.generateMipmap(a.texture_type),a.unbind(0)),this.properties.name&&(b.storeTexture?b.storeTexture(this.properties.name,a):b.getTexturesContainer()[this.properties.name]=a),this._texture=a,this.setOutputData(0,a),this.setOutputData(1,this.properties.name))},F.registerNodeType("texture/save",q),p.widgets_info={uvcode:{widget:"code"},pixelcode:{widget:"code"},precision:{widget:"combo",
+values:b.MODE_VALUES}},p.title="Operation",p.desc="Texture shader operation",p.presets={},p.prototype.getExtraMenuOptions=function(a){var c=this;return[{content:c.properties.show?"Hide Texture":"Show Texture",callback:function(){c.properties.show=!c.properties.show}}]},p.prototype.onPropertyChanged=function(){this.has_error=!1},p.prototype.onDrawBackground=function(a){this.flags.collapsed||20>=this.size[1]||!this.properties.show||!this._tex||this._tex.gl!=a||(a.save(),a.drawImage(this._tex,0,0,this.size[0],
+this.size[1]),a.restore())},p.prototype.onExecute=function(){var a=this.getInputData(0);if(this.isOutputConnected(0))if(this.properties.precision===b.PASS_THROUGH)this.setOutputData(0,a);else{var c=this.getInputData(1);if(this.properties.uvcode||this.properties.pixelcode){var d=512,f=512;a?(d=a.width,f=a.height):c&&(d=c.width,f=c.height);c||(c=GL.Texture.getWhiteTexture());var g=b.getTextureType(this.properties.precision,a);this._tex=a||this._tex?b.getTargetTexture(a||this._tex,this._tex,this.properties.precision):
+new GL.Texture(d,f,{type:g,format:gl.RGBA,filter:gl.LINEAR});g="";this.properties.uvcode&&(g="uv = "+this.properties.uvcode,-1!=this.properties.uvcode.indexOf(";")&&(g=this.properties.uvcode));var e="";this.properties.pixelcode&&(e="result = "+this.properties.pixelcode,-1!=this.properties.pixelcode.indexOf(";")&&(e=this.properties.pixelcode));var k=this._shader;if(!(this.has_error||k&&this._shader_code==g+"|"+e)){var h=b.replaceCode(p.pixel_shader,{UV_CODE:g,PIXEL_CODE:e});try{k=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,
+h),this.boxcolor="#00FF00"}catch(n){GL.Shader.dumpErrorToConsole(n,Shader.SCREEN_VERTEX_SHADER,h);this.boxcolor="#FF0000";this.has_error=!0;return}this._shader=k;this._shader_code=g+"|"+e}if(this._shader){var s=this.getInputData(2);null!=s?this.properties.value=s:s=parseFloat(this.properties.value);var l=this.graph.getTime();this._tex.drawTo(function(){gl.disable(gl.DEPTH_TEST);gl.disable(gl.CULL_FACE);gl.disable(gl.BLEND);a&&a.bind(0);c&&c.bind(1);var b=Mesh.getScreenQuad();k.uniforms({u_texture:0,
+u_textureB:1,value:s,texSize:[d,f],time:l}).draw(b)});this.setOutputData(0,this._tex)}}}},p.pixel_shader="precision highp float;\n\t\t\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tvarying vec2 v_coord;\n\t\tuniform vec2 texSize;\n\t\tuniform float time;\n\t\tuniform float value;\n\t\t\n\t\tvoid main() {\n\t\t\tvec2 uv = v_coord;\n\t\t\t{{UV_CODE}};\n\t\t\tvec4 color4 = texture2D(u_texture, uv);\n\t\t\tvec3 color = color4.rgb;\n\t\t\tvec4 color4B = texture2D(u_textureB, uv);\n\t\t\tvec3 colorB = color4B.rgb;\n\t\t\tvec3 result = color;\n\t\t\tfloat alpha = 1.0;\n\t\t\t{{PIXEL_CODE}};\n\t\t\tgl_FragColor = vec4(result, alpha);\n\t\t}\n\t\t",
+p.registerPreset=function(a,c){p.presets[a]=c},p.registerPreset("",""),p.registerPreset("bypass","color"),p.registerPreset("add","color + colorB * value"),p.registerPreset("substract","(color - colorB) * value"),p.registerPreset("mate","mix( color, colorB, color4B.a * value)"),p.registerPreset("invert","vec3(1.0) - color"),p.registerPreset("multiply","color * colorB * value"),p.registerPreset("divide","(color / colorB) / value"),p.registerPreset("difference","abs(color - colorB) * value"),p.registerPreset("max",
"max(color, colorB) * value"),p.registerPreset("min","min(color, colorB) * value"),p.registerPreset("displace","texture2D(u_texture, uv + (colorB.xy - vec2(0.5)) * value).xyz"),p.registerPreset("grayscale","vec3(color.x + color.y + color.z) * value / 3.0"),p.registerPreset("saturation","mix( vec3(color.x + color.y + color.z) / 3.0, color, value )"),p.registerPreset("threshold","vec3(color.x > colorB.x * value ? 1.0 : 0.0,color.y > colorB.y * value ? 1.0 : 0.0,color.z > colorB.z * value ? 1.0 : 0.0)"),
-p.prototype.onInspect=function(a){var b=this;a.addCombo("Presets","",{values:Object.keys(p.presets),callback:function(c){var d=p.presets[c];d&&(b.setProperty("pixelcode",d),b.title=c,a.refresh())}})},D.registerNodeType("texture/operation",p),r.title="Shader",r.desc="Texture shader",r.widgets_info={code:{type:"code"},precision:{widget:"combo",values:c.MODE_VALUES}},r.prototype.onPropertyChanged=function(a,b){if("code"==a){var c=this.getShader();if(c){var d=c.uniformInfo;if(this.inputs)for(var e={},
-h=0;h lumaMax))\n\t\t\t\tcolor = vec4(rgbA, 1.0);\n\t\t\telse\n\t\t\t\tcolor = vec4(rgbB, 1.0);\n\t\t\tif(u_igamma != 1.0)\n\t\t\t\tcolor.xyz = pow( color.xyz, vec3(u_igamma) );\n\t\t\treturn color;\n\t\t}\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\t\t}\n\t\t",
-s.gamma_pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_igamma;\n\t\tvoid main() {\n\t\t\tvec4 color = texture2D( u_texture, v_coord);\n\t\t\tcolor.xyz = pow(color.xyz, vec3(u_igamma) );\n\t\t gl_FragColor = color;\n\t\t}\n\t\t",D.registerNodeType("texture/toviewport",s),u.title="Copy",u.desc="Copy Texture",u.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",
-values:c.MODE_VALUES}},u.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)){if(a){var b=a.width,d=a.height;0!=this.properties.size&&(d=b=this.properties.size);var e=this._temp_texture,h=a.type;this.properties.precision===c.LOW?h=gl.UNSIGNED_BYTE:this.properties.precision===c.HIGH&&(h=gl.HIGH_PRECISION_FORMAT);e&&e.width==b&&e.height==d&&e.type==h||(e=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(b)&&isPowerOfTwo(d)&&(e=gl.LINEAR_MIPMAP_LINEAR),
-this._temp_texture=new GL.Texture(b,d,{type:h,format:gl.RGBA,minFilter:e,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}},D.registerNodeType("texture/copy",u),z.title="Downsample",z.desc="Downsample Texture",z.widgets_info={iterations:{type:"number",step:1,precision:0,min:0},precision:{widget:"combo",values:c.MODE_VALUES}},
-z.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)&&a&&a.texture_type===GL.TEXTURE_2D)if(1>this.properties.iterations)this.setOutputData(0,a);else{var b=z._shader;b||(z._shader=b=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,z.pixel_shader));var d=a.width|0,e=a.height|0,h=a.type;this.properties.precision===c.LOW?h=gl.UNSIGNED_BYTE:this.properties.precision===c.HIGH&&(h=gl.HIGH_PRECISION_FORMAT);var f=this.properties.iterations||1,k=a,g=
-null,l=[],a={type:h,format:a.format},h=vec2.create(),m={u_offset:h};this._texture&&GL.Texture.releaseTemporary(this._texture);for(var n=0;n>1||0;e=e>>1||0;g=GL.Texture.getTemporary(d,e,a);l.push(g);k.setParameter(GL.TEXTURE_MAG_FILTER,GL.NEAREST);k.copyTo(g,b,m);if(1==d&&1==e)break;k=g}this._texture=l.pop();for(n=0;n>=2,d++,1!=c););a.copyTo(this._textures_chain[0]);for(var d=1;d<=this._textures_chain.length;++d)a=this._textures_chain[d];var e=v._shader,h=this._uniforms;h.u_mipmap_offset=this.properties.mipmap_offset;gl.disable(gl.DEPTH_TEST);
-gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){a.toViewport(e,h)})}},v.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tuniform mat4 u_samples_a;\n\t\tuniform mat4 u_samples_b;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_mipmap_offset;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 color = vec4(0.0);\n\t\t\t//random average\n\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t{\n\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t}\n\t\t gl_FragColor = color * 0.03125;\n\t\t}\n\t\t",
-k.title="Smooth",k.desc="Smooth texture over time",k.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){k._shader||(k._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,k.pixel_shader));var b=this._temp_texture;b&&b.type==a.type&&b.width==a.width&&b.height==a.height||(b={type:a.type,format:gl.RGBA,filter:gl.NEAREST},this._temp_texture=new GL.Texture(a.width,a.height,b),this._temp_texture2=new GL.Texture(a.width,a.height,b),a.copyTo(this._temp_texture2));var b=
-this._temp_texture,c=this._temp_texture2,d=k._shader,e=this._uniforms;e.u_factor=1-this.getInputOrProperty("factor");gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);b.drawTo(function(){c.bind(1);a.toViewport(d,e)});this.setOutputData(0,b);this._temp_texture=c;this._temp_texture2=b}},k.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_factor;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tgl_FragColor = mix( texture2D( u_texture, v_coord ), texture2D( u_textureB, v_coord ), u_factor );\n\t\t}\n\t\t",
-D.registerNodeType("texture/temporal_smooth",k),m.title="Lineal Avg Smooth",m.desc="Smooth texture linearly over time",m["@samples"]={type:"number",min:1,max:64,step:1,precision:1},m.prototype.getPreviewTexture=function(){return this._temp_texture2},m.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){m._shader||(m._shader_copy=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,m.pixel_shader_copy),m._shader_avg=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,m.pixel_shader_avg));
-var b=Math.clamp(this.properties.samples,0,64),c=this.frame,d=this.properties.frames_interval;if(0==d||0==c%d){c=this._temp_texture;c&&c.type==a.type&&c.width==b||(c={type:a.type,format:gl.RGBA,filter:gl.NEAREST},this._temp_texture=new GL.Texture(b,1,c),this._temp_texture2=new GL.Texture(b,1,c),this._temp_texture_out=new GL.Texture(1,1,c));var e=this._temp_texture,h=this._temp_texture2,f=m._shader_copy,k=m._shader_avg,g=this._uniforms;g.u_samples=b;g.u_isamples=1/b;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);
-e.drawTo(function(){h.bind(1);a.toViewport(f,g)});this._temp_texture_out.drawTo(function(){e.toViewport(k,g)});this.setOutputData(0,this._temp_texture_out);this._temp_texture=h;this._temp_texture2=e}else this.setOutputData(0,this._temp_texture_out);this.setOutputData(1,this._temp_texture2);this.frame++}},m.pixel_shader_copy="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_isamples;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tif( v_coord.x <= u_isamples )\n\t\t\t\tgl_FragColor = texture2D( u_texture, vec2(0.5) );\n\t\t\telse\n\t\t\t\tgl_FragColor = texture2D( u_textureB, v_coord - vec2(u_isamples,0.0) );\n\t\t}\n\t\t",
-m.pixel_shader_avg="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform int u_samples;\n\t\tuniform float u_isamples;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 color = vec4(0.0);\n\t\t\tfor(int i = 0; i < 64; ++i)\n\t\t\t{\n\t\t\t\tcolor += texture2D( u_texture, vec2( float(i)*u_isamples,0.0) );\n\t\t\t\tif(i == (u_samples - 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgl_FragColor = color * u_isamples;\n\t\t}\n\t\t",D.registerNodeType("texture/linear_avg_smooth",
-m),C.title="Image to Texture",C.desc="Uploads an image to the GPU",C.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var b=a.videoWidth||a.width,c=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0,a.gltexture);else{var d=this._temp_texture;d&&d.width==b&&d.height==c||(this._temp_texture=new GL.Texture(b,c,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(e){console.error("image comes from an unsafe location, cannot be uploaded to webgl: "+e);
-return}this.setOutputData(0,this._temp_texture)}}},D.registerNodeType("texture/imageToTexture",C),h.widgets_info={texture:{widget:"texture"},precision:{widget:"combo",values:c.MODE_VALUES}},h.title="LUT",h.desc="Apply LUT to Texture",h.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===c.PASS_THROUGH||!1===this.properties.enabled)this.setOutputData(0,a);else if(a){var b=this.getInputData(1);b||(b=c.getTexture(this.properties.texture));
-if(b){b.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);var d=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=d=this.getInputData(2));this._tex=c.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){b.bind(1);a.toViewport(h._shader,{u_texture:0,u_textureB:1,
-u_amount:d})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}}},h.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_amount;\n\t\t\n\t\tvoid main() {\n\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t mediump vec2 quad1;\n\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t mediump vec2 quad2;\n\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t highp vec2 texPos1;\n\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t highp vec2 texPos2;\n\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t}\n\t\t",
-D.registerNodeType("texture/LUT",h),t.title="Texture to Channels",t.desc="Split texture channels",t.prototype.onExecute=function(){var a=this.getInputData(0);if(a){this._channels||(this._channels=Array(4));for(var b=gl.RGB,c=0,d=0;4>d;d++)this.isOutputConnected(d)?(this._channels[d]&&this._channels[d].width==a.width&&this._channels[d].height==a.height&&this._channels[d].type==a.type&&this._channels[d].format==b||(this._channels[d]=new GL.Texture(a.width,a.height,{type:a.type,format:b,filter:gl.LINEAR})),
-c++):this._channels[d]=null;if(c){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);for(var e=Mesh.getScreenQuad(),h=t._shader,f=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],d=0;4>d;d++)this._channels[d]&&(this._channels[d].drawTo(function(){a.bind(0);h.uniforms({u_texture:0,u_mask:f[d]}).draw(e)}),this.setOutputData(d,this._channels[d]))}}},t.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec4 u_mask;\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t}\n\t\t",
-D.registerNodeType("texture/textureChannels",t),n.title="Channels to Texture",n.desc="Split texture channels",n.widgets_info={precision:{widget:"combo",values:c.MODE_VALUES}},n.prototype.onExecute=function(){var a=c.getWhiteTexture(),b=this.getInputData(0)||a,d=this.getInputData(1)||a,e=this.getInputData(2)||a,h=this.getInputData(3)||a;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var f=Mesh.getScreenQuad();n._shader||(n._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,n.pixel_shader));var k=n._shader,
-a=Math.max(b.width,d.width,e.width,h.width),g=Math.max(b.height,d.height,e.height,h.height),l=this.properties.precision==c.HIGH?c.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._texture&&this._texture.width==a&&this._texture.height==g&&this._texture.type==l||(this._texture=new GL.Texture(a,g,{type:l,format:gl.RGBA,filter:gl.LINEAR}));a=this._color;a[0]=this.properties.R;a[1]=this.properties.G;a[2]=this.properties.B;a[3]=this.properties.A;var m=this._uniforms;this._texture.drawTo(function(){b.bind(0);
-d.bind(1);e.bind(2);h.bind(3);k.uniforms(m).draw(f)});this.setOutputData(0,this._texture)},n.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_textureR;\n\t\tuniform sampler2D u_textureG;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform sampler2D u_textureA;\n\t\tuniform vec4 u_color;\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = u_color * vec4( \t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t}\n\t\t",
-D.registerNodeType("texture/channelsTexture",n),a.title="Color",a.desc="Generates a 1x1 texture with a constant color",a.widgets_info={precision:{widget:"combo",values:c.MODE_VALUES}},a.prototype.onDrawBackground=function(a){var b=this.properties.color;a.fillStyle="rgb("+Math.floor(255*Math.clamp(b[0],0,1))+","+Math.floor(255*Math.clamp(b[1],0,1))+","+Math.floor(255*Math.clamp(b[2],0,1))+")";this.flags.collapsed?this.boxcolor=a.fillStyle:a.fillRect(0,0,this.size[0],this.size[1])},a.prototype.onExecute=
-function(){var a=this.properties.precision==c.HIGH?c.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._tex&&this._tex.type==a||(this._tex=new GL.Texture(1,1,{format:gl.RGBA,type:a,minFilter:gl.NEAREST}));a=this.properties.color;if(this.inputs)for(var b=0;ba.width?b:
-a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var f=Mesh.getScreenQuad(),k=null,g=this._uniforms;e?(k=d._shader_tex,k||(k=d._shader_tex=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,d.pixel_shader,{MIX_TEX:""}))):(k=d._shader_factor,k||(k=d._shader_factor=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,d.pixel_shader)),h=null==h?this.properties.factor:h,g.u_mix.set([h,h,h,h]));var l=this.properties.invert;this._tex.drawTo(function(){a.bind(l?1:0);b.bind(l?0:1);e&&e.bind(2);
-k.uniforms(g).draw(f)});this.setOutputData(0,this._tex)}}},d.prototype.onGetInputs=function(){return[["factor","number"]]},d.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_textureA;\n\t\tuniform sampler2D u_textureB;\n\t\t#ifdef MIX_TEX\n\t\t\tuniform sampler2D u_textureMix;\n\t\t#else\n\t\t\tuniform vec4 u_mix;\n\t\t#endif\n\t\t\n\t\tvoid main() {\n\t\t\t#ifdef MIX_TEX\n\t\t\t vec4 f = texture2D(u_textureMix, v_coord);\n\t\t\t#else\n\t\t\t vec4 f = u_mix;\n\t\t\t#endif\n\t\t gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), f );\n\t\t}\n\t\t",
-D.registerNodeType("texture/mix",d),x.title="Edges",x.desc="Detects edges",x.widgets_info={precision:{widget:"combo",values:c.MODE_VALUES}},x.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===c.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=c.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var b=Mesh.getScreenQuad(),d=x._shader,e=this.properties.invert,h=this.properties.factor,
-f=this.properties.threshold?1:0;this._tex.drawTo(function(){a.bind(0);d.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height],u_factor:h,u_threshold:f,u_invert:e?1:0}).draw(b)});this.setOutputData(0,this._tex)}}},x.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_isize;\n\t\tuniform int u_invert;\n\t\tuniform float u_factor;\n\t\tuniform float u_threshold;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\tdiff *= u_factor;\n\t\t\tif(u_invert == 1)\n\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\tif( u_threshold == 0.0 )\n\t\t\t\tgl_FragColor = vec4( diff.xyz, center.a );\n\t\t\telse\n\t\t\t\tgl_FragColor = vec4( diff.x > 0.5 ? 1.0 : 0.0, diff.y > 0.5 ? 1.0 : 0.0, diff.z > 0.5 ? 1.0 : 0.0, center.a );\n\t\t}\n\t\t",
-D.registerNodeType("texture/edges",x),l.title="Depth Range",l.desc="Generates a texture with a depth range",l.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(a){var b=gl.UNSIGNED_BYTE;this.properties.high_precision&&(b=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==b&&this._temp_texture.width==a.width&&this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:b,format:gl.RGBA,
-filter:gl.LINEAR}));var c=this._uniforms,b=this.properties.distance;this.isInputConnected(1)&&(b=this.getInputData(1),this.properties.distance=b);var d=this.properties.range;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.range=d);c.u_distance=b;c.u_range=d;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad();l._shader||(l._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader),l._shader_onlydepth=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,l.pixel_shader,
-{ONLY_DEPTH:""}));var h=this.properties.only_depth?l._shader_onlydepth:l._shader,b=null,b=a.near_far_planes?a.near_far_planes:window.LS&&LS.Renderer._main_camera?LS.Renderer._main_camera._uniforms.u_camera_planes:[0.1,1E3];c.u_camera_planes=b;this._temp_texture.drawTo(function(){a.bind(0);h.uniforms(c).draw(e)});this._temp_texture.near_far_planes=b;this.setOutputData(0,this._temp_texture)}}},l.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_camera_planes;\n\t\tuniform float u_distance;\n\t\tuniform float u_range;\n\t\t\n\t\tfloat LinearDepth()\n\t\t{\n\t\t\tfloat zNear = u_camera_planes.x;\n\t\t\tfloat zFar = u_camera_planes.y;\n\t\t\tfloat depth = texture2D(u_texture, v_coord).x;\n\t\t\tdepth = depth * 2.0 - 1.0;\n\t\t\treturn zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\t\t}\n\t\t\n\t\tvoid main() {\n\t\t\tfloat depth = LinearDepth();\n\t\t\t#ifdef ONLY_DEPTH\n\t\t\t gl_FragColor = vec4(depth);\n\t\t\t#else\n\t\t\t\tfloat diff = abs(depth * u_camera_planes.y - u_distance);\n\t\t\t\tfloat dof = 1.0;\n\t\t\t\tif(diff <= u_range)\n\t\t\t\t\tdof = diff / u_range;\n\t\t\t gl_FragColor = vec4(dof);\n\t\t\t#endif\n\t\t}\n\t\t",
-D.registerNodeType("texture/depth_range",l),K.title="Blur",K.desc="Blur a texture",K.widgets_info={precision:{widget:"combo",values:c.MODE_VALUES}},K.max_iterations=20,K.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b=this._final_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(b=this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));var c=this.properties.iterations;this.isInputConnected(1)&&
-(c=this.getInputData(1),this.properties.iterations=c);c=Math.min(Math.floor(c),K.max_iterations);if(0==c)this.setOutputData(0,a);else{var d=this.properties.intensity;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.intensity=d);var e=D.camera_aspect;e||void 0===window.gl||(e=gl.canvas.height/gl.canvas.width);e||(e=1);var e=this.properties.preserve_aspect?e:1,h=this.properties.scale||[1,1];a.applyBlur(e*h[0],h[1],d,b);for(a=1;a>=1;1<(d|0)&&(d>>=1);if(2>b)break;l=k[s]=GL.Texture.getTemporary(b,d,e);t[0]=1/m.width;t[1]=1/m.height;m.blit(l,g.uniforms(f));m=l}this.isOutputConnected(2)&&(b=this._average_texture,b&&b.type==a.type&&b.format==a.format||(b=this._average_texture=new GL.Texture(1,1,{type:a.type,format:a.format,filter:gl.LINEAR})),t[0]=1/m.width,t[1]=1/m.height,f.u_intensity=p,f.u_delta=1,m.blit(b,g.uniforms(f)),this.setOutputData(2,b));gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);f.u_intensity=
-this.getInputOrProperty("persistence");f.u_delta=0.5;for(s-=2;0<=s;s--)l=k[s],k[s]=null,t[0]=1/m.width,t[1]=1/m.height,m.blit(l,g.uniforms(f)),GL.Texture.releaseTemporary(m),m=l;gl.disable(gl.BLEND);this.isOutputConnected(1)&&(k=this._glow_texture,k&&k.width==a.width&&k.height==a.height&&k.type==h&&k.format==a.format||(k=this._glow_texture=new GL.Texture(a.width,a.height,{type:h,format:a.format,filter:gl.LINEAR})),m.blit(k),this.setOutputData(1,k));if(this.isOutputConnected(0)){k=this._final_texture;
-k&&k.width==a.width&&k.height==a.height&&k.type==h&&k.format==a.format||(k=this._final_texture=new GL.Texture(a.width,a.height,{type:h,format:a.format,filter:gl.LINEAR}));var r=this.getInputData(1),q=this.getInputOrProperty("dirt_factor");f.u_intensity=p;g=r?E._dirt_final_shader:E._final_shader;g||(g=r?E._dirt_final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,E.final_pixel_shader,{USE_DIRT:""}):E._final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,E.final_pixel_shader));k.drawTo(function(){a.bind(0);
-m.bind(1);r&&(g.setUniform("u_dirt_factor",q),g.setUniform("u_dirt_texture",r.bind(2)));g.toViewport(f)});this.setOutputData(0,k)}GL.Texture.releaseTemporary(m)}},E.cut_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform float u_threshold;\n\tvoid main() {\n\t\tgl_FragColor = max( texture2D( u_texture, v_coord ) - vec4( u_threshold ), vec4(0.0) );\n\t}",E.scale_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform vec2 u_texel_size;\n\tuniform float u_delta;\n\tuniform float u_intensity;\n\t\n\tvec4 sampleBox(vec2 uv) {\n\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\tvec4 s = texture2D( u_texture, uv + o.xy ) + texture2D( u_texture, uv + o.zy) + texture2D( u_texture, uv + o.xw) + texture2D( u_texture, uv + o.zw);\n\t\treturn s * 0.25;\n\t}\n\tvoid main() {\n\t\tgl_FragColor = u_intensity * sampleBox( v_coord );\n\t}",
-E.final_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform sampler2D u_glow_texture;\n\t#ifdef USE_DIRT\n\t\tuniform sampler2D u_dirt_texture;\n\t#endif\n\tuniform vec2 u_texel_size;\n\tuniform float u_delta;\n\tuniform float u_intensity;\n\tuniform float u_dirt_factor;\n\t\n\tvec4 sampleBox(vec2 uv) {\n\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\tvec4 s = texture2D( u_glow_texture, uv + o.xy ) + texture2D( u_glow_texture, uv + o.zy) + texture2D( u_glow_texture, uv + o.xw) + texture2D( u_glow_texture, uv + o.zw);\n\t\treturn s * 0.25;\n\t}\n\tvoid main() {\n\t\tvec4 glow = sampleBox( v_coord );\n\t\t#ifdef USE_DIRT\n\t\t\tglow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\t\t#endif\n\t\tgl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\t}",
-D.registerNodeType("texture/glow",E),G.title="Kuwahara Filter",G.desc="Filters a texture giving an artistic oil canvas painting",G.max_radius=10,G._shaders=[],G.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));b=this.properties.radius;b=Math.min(Math.floor(b),G.max_radius);if(0==
-b)this.setOutputData(0,a);else{var c=this.properties.intensity,d=D.camera_aspect;d||void 0===window.gl||(d=gl.canvas.height/gl.canvas.width);d||(d=1);d=this.properties.preserve_aspect?d:1;G._shaders[b]||(G._shaders[b]=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,G.pixel_shader,{RADIUS:b.toFixed(0)}));var e=G._shaders[b],h=GL.Mesh.getScreenQuad();a.bind(0);this._temp_texture.drawTo(function(){e.uniforms({u_texture:0,u_intensity:c,u_resolution:[a.width,a.height],u_iResolution:[1/a.width,1/a.height]}).draw(h)});
-this.setOutputData(0,this._temp_texture)}}},G.pixel_shader="\nprecision highp float;\nvarying vec2 v_coord;\nuniform sampler2D u_texture;\nuniform float u_intensity;\nuniform vec2 u_resolution;\nuniform vec2 u_iResolution;\n#ifndef RADIUS\n\t#define RADIUS 7\n#endif\nvoid main() {\n\n\tconst int radius = RADIUS;\n\tvec2 fragCoord = v_coord;\n\tvec2 src_size = u_iResolution;\n\tvec2 uv = v_coord;\n\tfloat n = float((radius + 1) * (radius + 1));\n\tint i;\n\tint j;\n\tvec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0);\n\tvec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0);\n\tvec3 c;\n\t\n\tfor (int j = -radius; j <= 0; ++j) {\n\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm0 += c;\n\t\t\ts0 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = -radius; j <= 0; ++j) {\n\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm1 += c;\n\t\t\ts1 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = 0; j <= radius; ++j) {\n\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm2 += c;\n\t\t\ts2 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = 0; j <= radius; ++j) {\n\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm3 += c;\n\t\t\ts3 += c * c;\n\t\t}\n\t}\n\t\n\tfloat min_sigma2 = 1e+2;\n\tm0 /= n;\n\ts0 = abs(s0 / n - m0 * m0);\n\t\n\tfloat sigma2 = s0.r + s0.g + s0.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m0, 1.0);\n\t}\n\t\n\tm1 /= n;\n\ts1 = abs(s1 / n - m1 * m1);\n\t\n\tsigma2 = s1.r + s1.g + s1.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m1, 1.0);\n\t}\n\t\n\tm2 /= n;\n\ts2 = abs(s2 / n - m2 * m2);\n\t\n\tsigma2 = s2.r + s2.g + s2.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m2, 1.0);\n\t}\n\t\n\tm3 /= n;\n\ts3 = abs(s3 / n - m3 * m3);\n\t\n\tsigma2 = s3.r + s3.g + s3.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m3, 1.0);\n\t}\n}\n",
-D.registerNodeType("texture/kuwahara",G),H.title="XDoG Filter",H.desc="Filters a texture giving an artistic ink style",H.max_radius=10,H._shaders=[],H.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var b=this._temp_texture;b&&b.width==a.width&&b.height==a.height&&b.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));H._xdog_shader||(H._xdog_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,H.xdog_pixel_shader));
-var c=H._xdog_shader,d=GL.Mesh.getScreenQuad(),e=this.properties.sigma,h=this.properties.k,f=this.properties.p,k=this.properties.epsilon,g=this.properties.phi;a.bind(0);this._temp_texture.drawTo(function(){c.uniforms({src:0,sigma:e,k:h,p:f,epsilon:k,phi:g,cvsWidth:a.width,cvsHeight:a.height}).draw(d)});this.setOutputData(0,this._temp_texture)}},H.xdog_pixel_shader="\nprecision highp float;\nuniform sampler2D src;\n\nuniform float cvsHeight;\nuniform float cvsWidth;\n\nuniform float sigma;\nuniform float k;\nuniform float p;\nuniform float epsilon;\nuniform float phi;\nvarying vec2 v_coord;\n\nfloat cosh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat cosH = (tmp + 1.0 / tmp) / 2.0;\n\treturn cosH;\n}\n\nfloat tanh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat tanH = (tmp - 1.0 / tmp) / (tmp + 1.0 / tmp);\n\treturn tanH;\n}\n\nfloat sinh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat sinH = (tmp - 1.0 / tmp) / 2.0;\n\treturn sinH;\n}\n\nvoid main(void){\n\tvec3 destColor = vec3(0.0);\n\tfloat tFrag = 1.0 / cvsHeight;\n\tfloat sFrag = 1.0 / cvsWidth;\n\tvec2 Frag = vec2(sFrag,tFrag);\n\tvec2 uv = gl_FragCoord.st;\n\tfloat twoSigmaESquared = 2.0 * sigma * sigma;\n\tfloat twoSigmaRSquared = twoSigmaESquared * k * k;\n\tint halfWidth = int(ceil( 1.0 * sigma * k ));\n\n\tconst int MAX_NUM_ITERATION = 99999;\n\tvec2 sum = vec2(0.0);\n\tvec2 norm = vec2(0.0);\n\n\tfor(int cnt=0;cnt (2*halfWidth+1)*(2*halfWidth+1)){break;}\n\t\tint i = int(cnt / (2*halfWidth+1)) - halfWidth;\n\t\tint j = cnt - halfWidth - int(cnt / (2*halfWidth+1)) * (2*halfWidth+1);\n\n\t\tfloat d = length(vec2(i,j));\n\t\tvec2 kernel = vec2( exp( -d * d / twoSigmaESquared ), \n\t\t\t\t\t\t\texp( -d * d / twoSigmaRSquared ));\n\n\t\tvec2 L = texture2D(src, (uv + vec2(i,j)) * Frag).xx;\n\n\t\tnorm += kernel;\n\t\tsum += kernel * L;\n\t}\n\n\tsum /= norm;\n\n\tfloat H = 100.0 * ((1.0 + p) * sum.x - p * sum.y);\n\tfloat edge = ( H > epsilon )? 1.0 : 1.0 + tanh( phi * (H - epsilon));\n\tdestColor = vec3(edge);\n\tgl_FragColor = vec4(destColor, 1.0);\n}",
-D.registerNodeType("texture/xDoG",H),F.title="Webcam",F.desc="Webcam texture",F.is_webcam_open=!1,F.prototype.openStream=function(){function a(c){F.is_webcam_open=!1;console.log("Webcam rejected",c);b._webcam_stream=!1;b.boxcolor="red";b.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation=!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](a);var b=this}},F.prototype.closeStream=function(){if(this._webcam_stream){var a=
-this._webcam_stream.getTracks();if(a.length)for(var b=0;b=this.size[1]||!this._video||(a.save(),a.webgl?this._video_texture&&a.drawImage(this._video_texture,0,0,this.size[0],this.size[1]):a.drawImage(this._video,
-0,0,this.size[0],this.size[1]),a.restore())},F.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream();if(this._video&&this._video.videoWidth){var a=this._video.videoWidth,b=this._video.videoHeight,d=this._video_texture;d&&d.width==a&&d.height==b||(this._video_texture=new GL.Texture(a,b,{format:gl.RGB,filter:gl.LINEAR}));this._video_texture.uploadImage(this._video);this._video_texture.version=++this.version;this.properties.texture_name&&(c.getTexturesContainer()[this.properties.texture_name]=
-this._video_texture);this.setOutputData(0,this._video_texture);for(a=1;a= res)\n\t\t\t\t\tbreak;\n\t\t\t\tiCount++;\n\t\t\t}\n\t\t\tfloat nf = n/normK;\n\t\t\treturn nf*nf*nf*nf;\n\t\t}\n\t\tvoid main() {\n\t\t\tvec2 uv = v_coord * u_scale * u_viewport + u_offset * u_scale;\n\t\t\tvec4 color = vec4( pNoise( uv, u_octaves ) * u_amplitude );\n\t\t\tgl_FragColor = color;\n\t\t}",
-D.registerNodeType("texture/perlin",J),L.title="Canvas2D",L.desc="Executes Canvas2D code inside a texture or the viewport.",L.help="Set width and height to 0 to match viewport size.",L.widgets_info={precision:{widget:"combo",values:c.MODE_VALUES},code:{type:"code"},width:{type:"Number",precision:0,step:1},height:{type:"Number",precision:0,step:1}},L.prototype.onPropertyChanged=function(a,b){"code"==a&&this.compileCode(b)},L.prototype.compileCode=function(a){this._func=null;if(D.allow_scripts)try{this._func=
-new Function("canvas","ctx","time","script","v",a),this.boxcolor="#00FF00"}catch(b){this.boxcolor="#FF0000",console.error("Error parsing script"),console.error(b)}},L.prototype.onExecute=function(){var a=this._func;a&&this.isOutputConnected(0)&&this.executeDraw(a)},L.prototype.executeDraw=function(a){var b=this.properties.width||gl.canvas.width,d=this.properties.height||gl.canvas.height,e=this._temp_texture,h=c.getTextureType(this.properties.precision);e&&e.width==b&&e.height==d&&e.type==h||(e=this._temp_texture=
-new GL.Texture(b,d,{format:gl.RGBA,filter:gl.LINEAR,type:h}));var f=this.getInputData(0),k=this.properties,g=this,l=this.graph.getTime(),m=gl,n=gl.canvas;if(this.properties.use_html_canvas||!w.enableWebGLCanvas)this._canvas?(n=this._canvas,m=this._ctx):(n=this._canvas=createCanvas(b.height),m=this._ctx=n.getContext("2d")),n.width=b,n.height=d;if(m==gl)e.drawTo(function(){gl.start2D();k.clear&&(gl.clearColor(0,0,0,0),gl.clear(gl.COLOR_BUFFER_BIT));try{a.draw?a.draw.call(g,n,m,l,a,f):a.call(g,n,m,l,
-a,f),g.boxcolor="#00FF00"}catch(b){g.boxcolor="#FF0000",console.error("Error executing script"),console.error(b)}gl.finish2D()});else{k.clear&&m.clearRect(0,0,n.width,n.height);try{a.draw?a.draw.call(this,n,m,l,a,f):a.call(this,n,m,l,a,f),this.boxcolor="#00FF00"}catch(t){this.boxcolor="#FF0000",console.error("Error executing script"),console.error(t)}e.uploadImage(n)}this.setOutputData(0,e)},D.registerNodeType("texture/canvas2D",L),M.title="Matte",M.desc="Extracts background",M.widgets_info={key_color:{widget:"color"},
-precision:{widget:"combo",values:c.MODE_VALUES}},M.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===c.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=c.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);this._uniforms||(this._uniforms={u_texture:0,u_key_color:this.properties.key_color,u_threshold:1,u_slope:1});var b=this._uniforms,d=Mesh.getScreenQuad(),e=M._shader;e||
-(e=M._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,M.pixel_shader));b.u_key_color=this.properties.key_color;b.u_threshold=this.properties.threshold;b.u_slope=this.properties.slope;this._tex.drawTo(function(){a.bind(0);e.uniforms(b).draw(d)});this.setOutputData(0,this._tex)}}},M.pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec3 u_key_color;\n\t\tuniform float u_threshold;\n\t\tuniform float u_slope;\n\t\t\n\t\tvoid main() {\n\t\t\tvec3 color = texture2D( u_texture, v_coord ).xyz;\n\t\t\tfloat diff = length( normalize(color) - normalize(u_key_color) );\n\t\t\tfloat edge = u_threshold * (1.0 - u_slope);\n\t\t\tfloat alpha = smoothstep( edge, u_threshold, diff);\n\t\t\tgl_FragColor = vec4( color, alpha );\n\t\t}",
-D.registerNodeType("texture/matte",M),N.title="CubemapToTexture2D",N.desc="Transforms a CUBEMAP texture into a TEXTURE2D in Polar Representation",N.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(a&&a.texture_type==GL.TEXTURE_CUBE_MAP){!this._last_tex||this._last_tex.height==a.height&&this._last_tex.type==a.type||(this._last_tex=null);var b=this.getInputOrProperty("yaw");this._last_tex=GL.Texture.cubemapToTexture2D(a,a.height,this._last_tex,!0,b);this.setOutputData(0,
-this._last_tex)}}},D.registerNodeType("texture/cubemapToTexture2D",N))})(this);
-(function(w){function c(){this.addOutput("out","geometry");this.addOutput("points","array");this.properties={radius:1,num_points:4096,regular:!1,mode:c.SPHERE};this.points=new Float32Array(3*this.properties.num_points);this.must_update=!0;this.version=0;this.geometry={vertices:null,_id:1E5*Math.random()|0}}function q(){this.addInput("mesh","mesh");this.addOutput("out","geometry");this.geometry={};this.last_mesh=null}function f(){this.addInput("in","geometry");this.addOutput("out","geometry");this.properties=
-{code:"V[1] += 0.01 * Math.sin(I + T*0.001);",execute_every_frame:!1};this.geometry=null;this.version=this.geometry_id=-1;this.must_update=!0;this.func=this.vertices=null}function p(){this.addInput("in","geometry");this.addOutput("out","geometry");this.properties={min_dist:0.4,max_dist:0.5,max_connections:0,probability:1};this.version=this.geometry_id=-1;this.my_version=1;this.must_update=!0}function r(){this.addInput("in","geometry");this.addInput("mat4","mat4");this.addInput("tex","texture");this.addOutput("mesh",
-"mesh");this.properties={enabled:!0,primitive:GL.TRIANGLES,additive:!1,color:[1,1,1],opacity:1};this.color=vec4.create([1,1,1,1]);this.uniforms={u_color:this.color};this.version=-1;this.mesh=null}function g(){this.addInput("in","geometry");this.addInput("mat4","mat4");this.addInput("tex","texture");this.properties={enabled:!0,point_size:0.1,fixed_size:!1,additive:!0,color:[1,1,1],opacity:1};this.color=vec4.create([1,1,1,1]);this.uniforms={u_point_size:1,u_perspective:1,u_point_perspective:1,u_color:this.color};
-this.version=this.geometry_id=-1;this.mesh=null}var y=w.LiteGraph,s=new Float32Array(16),u=new Float32Array(16),z=new Float32Array(16),e=new Float32Array(16),v={u_view:s,u_projection:u,u_viewprojection:z,u_model:e};y.LGraphRender={onRequestCameraMatrices:null};w.LGraphPoints3D=c;c.RECTANGLE=1;c.CIRCLE=2;c.CUBE=10;c.SPHERE=11;c.HEMISPHERE=12;c.INSIDE_SPHERE=13;c.MODE_VALUES={rectangle:c.RECTANGLE,circle:c.CIRCLE,cube:c.CUBE,sphere:c.SPHERE,hemisphere:c.HEMISPHERE,inside_sphere:c.INSIDE_SPHERE};c.widgets_info=
-{mode:{widget:"combo",values:c.MODE_VALUES}};c.title="list of points";c.desc="returns an array of points";c.prototype.onPropertyChanged=function(c,e){this.must_update=!0};c.prototype.onExecute=function(){this.must_update&&(this.must_update=!1,this.updatePoints());this.geometry.vertices=this.points;this.geometry._version=this.version;this.setOutputData(0,this.geometry)};c.generatePoints=function(e,f,g,h,t){var n=3*f;h&&h.length==n||(h=new Float32Array(n));if(t)if(g==c.RECTANGLE){n=Math.floor(Math.sqrt(f));
-for(f=0;fe&&(e=1);this.points.length!=3*e&&(this.points=new Float32Array(3*e));this.points=c.generatePoints(this.properties.radius,e,this.properties.mode,this.points,this.properties.regular);this.version++};y.registerNodeType("geometry/points3D",c);q.title="to geometry";q.desc="converts a mesh to geometry";q.prototype.onExecute=function(){var c=this.getInputData(0);if(c){if(c!=
-this.last_mesh){this.last_mesh=c;for(i in c.vertexBuffers)this.geometry[i]=c.vertexBuffers[i].data;c.indexBuffers.triangles&&(this.geometry.indices=c.indexBuffers.triangles.data);this.geometry._id=1E5*Math.random()|0;this.geometry._version=0}this.setOutputData(0,this.geometry);this.geometry&&this.setOutputData(1,this.geometry.vertices)}};y.registerNodeType("geometry/toGeometry",q);f.title="geoeval";f.desc="eval code";f.widgets_info={code:{widget:"code"}};f.prototype.onConfigure=function(c){this.compileCode()};
-f.prototype.compileCode=function(){if(this.properties.code)try{this.func=new Function("V","I","T",this.properties.code),this.boxcolor="#AFA",this.must_update=!0}catch(c){this.boxcolor="red"}};f.prototype.onPropertyChanged=function(c,e){"code"==c&&(this.properties.code=e,this.compileCode())};f.prototype.onExecute=function(){var c=this.getInputData(0);if(c)if(this.func){if(this.geometry_id!=c._id||this.version!=c._version||this.must_update||this.properties.execute_every_frame){this.must_update=!1;this.geometry_id=
-c._id;this.properties.execute_every_frame?this.version++:this.version=c._version;var e=this.func,f=getTime();this.geometry||(this.geometry={});for(var h in c)null!=c[h]&&(this.geometry[h]=c[h].constructor==Float32Array?new Float32Array(c[h]):c[h]);this.geometry._id=c._id;this.geometry._version=this.properties.execute_every_frame?this.version:c._version+1;var g=vec3.create(),n=this.vertices;n&&this.vertices.length==c.vertices.length?n.set(c.vertices):n=this.vertices=new Float32Array(c.vertices);for(h=
-0;hg||qn&&
-na))break}this.geometry.indices=this.indices=new Uint32Array(b)}this.indices&&this.indices.length?(this.geometry.indices=this.indices,this.setOutputData(0,this.geometry)):this.setOutputData(0,null)}};y.registerNodeType("geometry/connectPoints",p);"undefined"!=typeof GL&&(r.title="render",r.desc="renders a geometry",r.PRIMITIVE_VALUES={points:GL.POINTS,lines:GL.LINES,line_loop:GL.LINE_LOOP,line_strip:GL.LINE_STRIP,triangles:GL.TRIANGLES,triangle_fan:GL.TRIANGLE_FAN,
-triangle_strip:GL.TRIANGLE_STRIP},r.widgets_info={primitive:{widget:"combo",values:r.PRIMITIVE_VALUES},color:{widget:"color"}},r.prototype.updateMesh=function(c){this.mesh||(this.mesh=new GL.Mesh);for(var e in c)if("_"!=e[0]){var f=c[e],h=GL.Mesh.common_buffers[e];if(h||"indices"==e){var h=h?h.spacing:3,g=this.mesh.vertexBuffers[e];g&&g.data.length==f.length?(g.data.set(f),g.upload(GL.DYNAMIC_DRAW)):g=new GL.Buffer("indices"==e?GL.ELEMENT_ARRAY_BUFFER:GL.ARRAY_BUFFER,f,h,GL.DYNAMIC_DRAW);this.mesh.addBuffer(e,
-g)}}this.geometry_id=this.mesh.id=c._id;this.version=this.mesh.version=c._version;return this.mesh},r.prototype.onExecute=function(){if(this.properties.enabled){var c=this.getInputData(0);if(c)if(this.version==c._version&&this.geometry_id==c._id||this.updateMesh(c),y.LGraphRender.onRequestCameraMatrices){y.LGraphRender.onRequestCameraMatrices(s,u,z);c=null;this.getInputData(2)?(c=gl.shaders.textured)||(c=gl.shaders.textured=new GL.Shader(g.vertex_shader_code,g.fragment_shader_code,{USE_TEXTURE:""})):
-(c=gl.shaders.flat)||(c=gl.shaders.flat=new GL.Shader(g.vertex_shader_code,g.fragment_shader_code));this.color.set(this.properties.color);this.color[3]=this.properties.opacity;var f=this.getInputData(1);f?e.set(f):mat4.identity(e);this.uniforms.u_point_size=1;f=this.properties.primitive;c.uniforms(v);c.uniforms(this.uniforms);1<=this.properties.opacity?gl.disable(gl.BLEND):gl.enable(gl.BLEND);gl.enable(gl.DEPTH_TEST);this.properties.additive?(gl.blendFunc(gl.SRC_ALPHA,gl.ONE),gl.depthMask(!1)):gl.blendFunc(gl.SRC_ALPHA,
-gl.ONE_MINUS_SRC_ALPHA);c.draw(this.mesh,f,"indices");gl.disable(gl.BLEND);gl.depthMask(!0)}else console.warn("cannot render geometry, LiteGraph.onRequestCameraMatrices is null, remember to fill this with a callback(view_matrix, projection_matrix,viewprojection_matrix) to use 3D rendering from the graph")}},y.registerNodeType("geometry/render",r),g.widgets_info={color:{widget:"color"}},g.prototype.updateMesh=function(c){this.buffer&&this.buffer.data.length==c.vertices.length?(this.buffer.data.set(c.vertices),
-this.buffer.upload(GL.DYNAMIC_DRAW)):this.buffer=new GL.Buffer(GL.ARRAY_BUFFER,c.vertices,3,GL.DYNAMIC_DRAW);this.mesh||(this.mesh=new GL.Mesh);this.mesh.addBuffer("vertices",this.buffer);this.geometry_id=this.mesh.id=c._id;this.version=this.mesh.version=c._version},g.prototype.onExecute=function(){if(this.properties.enabled){var c=this.getInputData(0);if(c)if(this.version==c._version&&this.geometry_id==c._id||this.updateMesh(c),y.LGraphRender.onRequestCameraMatrices){y.LGraphRender.onRequestCameraMatrices(s,
-u,z);c=null;this.getInputData(2)?(c=gl.shaders.textured_points)||(c=gl.shaders.textured_points=new GL.Shader(g.vertex_shader_code,g.fragment_shader_code,{USE_TEXTURED_POINTS:""})):(c=gl.shaders.points)||(c=gl.shaders.points=new GL.Shader(g.vertex_shader_code,g.fragment_shader_code,{USE_POINTS:""}));this.color.set(this.properties.color);this.color[3]=this.properties.opacity;var f=this.getInputData(1);f?e.set(f):mat4.identity(e);this.uniforms.u_point_size=this.properties.point_size;this.uniforms.u_point_perspective=
-this.properties.fixed_size?0:1;this.uniforms.u_perspective=gl.viewport_data[3]*u[5];c.uniforms(v);c.uniforms(this.uniforms);1<=this.properties.opacity?gl.disable(gl.BLEND):gl.enable(gl.BLEND);gl.enable(gl.DEPTH_TEST);this.properties.additive?(gl.blendFunc(gl.SRC_ALPHA,gl.ONE),gl.depthMask(!1)):gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);c.draw(this.mesh,GL.POINTS);gl.disable(gl.BLEND);gl.depthMask(!0)}else console.warn("cannot render geometry, LiteGraph.onRequestCameraMatrices is null, remember to fill this with a callback(view_matrix, projection_matrix,viewprojection_matrix) to use 3D rendering from the graph")}},
-y.registerNodeType("geometry/render_points",g),g.vertex_shader_code="\t\tprecision mediump float;\n\t\tattribute vec3 a_vertex;\n\t\tvarying vec3 v_vertex;\n\t\tattribute vec3 a_normal;\n\t\tvarying vec3 v_normal;\n\t\t#ifdef USE_COLOR\n\t\t\tattribute vec4 a_color;\n\t\t\tvarying vec4 v_color;\n\t\t#endif\n\t\tattribute vec2 a_coord;\n\t\tvarying vec2 v_coord;\n\t\t#ifdef USE_SIZE\n\t\t\tattribute float a_extra;\n\t\t#endif\n\t\t#ifdef USE_INSTANCING\n\t\t\tattribute mat4 u_model;\n\t\t#else\n\t\t\tuniform mat4 u_model;\n\t\t#endif\n\t\tuniform mat4 u_viewprojection;\n\t\tuniform float u_point_size;\n\t\tuniform float u_perspective;\n\t\tuniform float u_point_perspective;\n\t\tfloat computePointSize(float radius, float w)\n\t\t{\n\t\t\tif(radius < 0.0)\n\t\t\t\treturn -radius;\n\t\t\treturn u_perspective * radius / w;\n\t\t}\n\t\tvoid main() {\n\t\t\tv_coord = a_coord;\n\t\t\t#ifdef USE_COLOR\n\t\t\t\tv_color = a_color;\n\t\t\t#endif\n\t\t\tv_vertex = ( u_model * vec4( a_vertex, 1.0 )).xyz;\n\t\t\tv_normal = ( u_model * vec4( a_normal, 0.0 )).xyz;\n\t\t\tgl_Position = u_viewprojection * vec4(v_vertex,1.0);\n\t\t\tgl_PointSize = u_point_size;\n\t\t\t#ifdef USE_SIZE\n\t\t\t\tgl_PointSize = a_extra;\n\t\t\t#endif\n\t\t\tif(u_point_perspective != 0.0)\n\t\t\t\tgl_PointSize = computePointSize( gl_PointSize, gl_Position.w );\n\t\t}\t",
-g.fragment_shader_code="\t\tprecision mediump float;\n\t\tuniform vec4 u_color;\n\t\t#ifdef USE_COLOR\n\t\t\tvarying vec4 v_color;\n\t\t#endif\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tvoid main() {\n\t\t\tvec4 color = u_color;\n\t\t\t#ifdef USE_TEXTURED_POINTS\n\t\t\t\tcolor *= texture2D(u_texture, gl_PointCoord.xy);\n\t\t\t#else\n\t\t\t\t#ifdef USE_TEXTURE\n\t\t\t\t color *= texture2D(u_texture, v_coord);\n\t\t\t\t if(color.a < 0.1)\n\t\t\t\t\tdiscard;\n\t\t\t\t#endif\n\t\t\t\t#ifdef USE_POINTS\n\t\t\t\t\tfloat dist = length( gl_PointCoord.xy - vec2(0.5) );\n\t\t\t\t\tif( dist > 0.45 )\n\t\t\t\t\t\tdiscard;\n\t\t\t\t#endif\n\t\t\t#endif\n\t\t\t#ifdef USE_COLOR\n\t\t\t\tcolor *= v_color;\n\t\t\t#endif\n\t\t\tgl_FragColor = color;\n\t\t}\t")})(this);
-(function(w){var c=w.LiteGraph;if("undefined"!=typeof GL){var q=function(){this.addInput("Texture","Texture");this.addInput("Aberration","number");this.addInput("Distortion","number");this.addInput("Blur","number");this.addOutput("Texture","Texture");this.properties={aberration:1,distortion:1,blur:1,precision:LGraphTexture.DEFAULT};q._shader||(q._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,q.pixel_shader),q._texture=new GL.Texture(3,1,{format:gl.RGB,wrap:gl.CLAMP_TO_EDGE,magFilter:gl.LINEAR,
-minFilter:gl.LINEAR,pixel_data:[255,0,0,0,255,0,0,0,255]}))};q.title="Lens";q.desc="Camera Lens distortion";q.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};q.prototype.onExecute=function(){var c=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,c);else if(c){this._tex=LGraphTexture.getTargetTexture(c,this._tex,this.properties.precision);var f=this.properties.aberration;this.isInputConnected(1)&&(f=this.getInputData(1),
-this.properties.aberration=f);var p=this.properties.distortion;this.isInputConnected(2)&&(p=this.getInputData(2),this.properties.distortion=p);var r=this.properties.blur;this.isInputConnected(3)&&(r=this.getInputData(3),this.properties.blur=r);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var w=Mesh.getScreenQuad(),e=q._shader;this._tex.drawTo(function(){c.bind(0);e.uniforms({u_texture:0,u_aberration:f,u_distortion:p,u_blur:r}).draw(w)});this.setOutputData(0,this._tex)}};q.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_aberration;\n\t\t\tuniform float u_distortion;\n\t\t\tuniform float u_blur;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 coord = v_coord;\n\t\t\t\tfloat dist = distance(vec2(0.5), coord);\n\t\t\t\tvec2 dist_coord = coord - vec2(0.5);\n\t\t\t\tfloat percent = 1.0 + ((0.5 - dist) / 0.5) * u_distortion;\n\t\t\t\tdist_coord *= percent;\n\t\t\t\tcoord = dist_coord + vec2(0.5);\n\t\t\t\tvec4 color = texture2D(u_texture,coord, u_blur * dist);\n\t\t\t\tcolor.r = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0+0.01*u_aberration), u_blur * dist ).r;\n\t\t\t\tcolor.b = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0-0.01*u_aberration), u_blur * dist ).b;\n\t\t\t\tgl_FragColor = color;\n\t\t\t}\n\t\t\t";
-c.registerNodeType("fx/lens",q);w.LGraphFXLens=q;var f=function(){this.addInput("Texture","Texture");this.addInput("Blurred","Texture");this.addInput("Mask","Texture");this.addInput("Threshold","number");this.addOutput("Texture","Texture");this.properties={shape:"",size:10,alpha:1,threshold:1,high_precision:!1}};f.title="Bokeh";f.desc="applies an Bokeh effect";f.widgets_info={shape:{widget:"texture"}};f.prototype.onExecute=function(){var c=this.getInputData(0),p=this.getInputData(1),r=this.getInputData(2);
-if(c&&r&&this.properties.shape){p||(p=c);var q=LGraphTexture.getTexture(this.properties.shape);if(q){var w=this.properties.threshold;this.isInputConnected(3)&&(w=this.getInputData(3),this.properties.threshold=w);var e=gl.UNSIGNED_BYTE;this.properties.high_precision&&(e=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==e&&this._temp_texture.width==c.width&&this._temp_texture.height==c.height||(this._temp_texture=new GL.Texture(c.width,c.height,{type:e,format:gl.RGBA,
-filter:gl.LINEAR}));var v=f._first_shader;v||(v=f._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,f._first_pixel_shader));var k=f._second_shader;k||(k=f._second_shader=new GL.Shader(f._second_vertex_shader,f._second_pixel_shader));var m=this._points_mesh;m&&m._width==c.width&&m._height==c.height&&2==m._spacing||(m=this.createPointsMesh(c.width,c.height,2));var C=Mesh.getScreenQuad(),h=this.properties.size,t=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){c.bind(0);
-p.bind(1);r.bind(2);v.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[c.width,c.height]}).draw(C)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);c.bind(0);q.bind(3);k.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:t,u_threshold:w,u_pointSize:h,u_itexsize:[1/c.width,1/c.height]}).draw(m,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,c)};f.prototype.createPointsMesh=function(c,f,p){for(var r=Math.round(c/p),q=Math.round(f/
-p),e=new Float32Array(r*q*2),v=-1,k=2/c*p,m=2/f*p,w=0;w lumaMax))\n\t\t\t\tcolor = vec4(rgbA, 1.0);\n\t\t\telse\n\t\t\t\tcolor = vec4(rgbB, 1.0);\n\t\t\tif(u_igamma != 1.0)\n\t\t\t\tcolor.xyz = pow( color.xyz, vec3(u_igamma) );\n\t\t\treturn color;\n\t\t}\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = applyFXAA( u_texture, v_coord * uViewportSize) ;\n\t\t}\n\t\t",
+v.gamma_pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_igamma;\n\t\tvoid main() {\n\t\t\tvec4 color = texture2D( u_texture, v_coord);\n\t\t\tcolor.xyz = pow(color.xyz, vec3(u_igamma) );\n\t\t gl_FragColor = color;\n\t\t}\n\t\t",F.registerNodeType("texture/toviewport",v),w.title="Copy",w.desc="Copy Texture",w.widgets_info={size:{widget:"combo",values:[0,32,64,128,256,512,1024,2048]},precision:{widget:"combo",
+values:b.MODE_VALUES}},w.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)){if(a){var c=a.width,d=a.height;0!=this.properties.size&&(d=c=this.properties.size);var f=this._temp_texture,g=a.type;this.properties.precision===b.LOW?g=gl.UNSIGNED_BYTE:this.properties.precision===b.HIGH&&(g=gl.HIGH_PRECISION_FORMAT);f&&f.width==c&&f.height==d&&f.type==g||(f=gl.LINEAR,this.properties.generate_mipmaps&&isPowerOfTwo(c)&&isPowerOfTwo(d)&&(f=gl.LINEAR_MIPMAP_LINEAR),
+this._temp_texture=new GL.Texture(c,d,{type:g,format:gl.RGBA,minFilter:f,magFilter:gl.LINEAR}));a.copyTo(this._temp_texture);this.properties.generate_mipmaps&&(this._temp_texture.bind(0),gl.generateMipmap(this._temp_texture.texture_type),this._temp_texture.unbind(0))}this.setOutputData(0,this._temp_texture)}},F.registerNodeType("texture/copy",w),B.title="Downsample",B.desc="Downsample Texture",B.widgets_info={iterations:{type:"number",step:1,precision:0,min:0},precision:{widget:"combo",values:b.MODE_VALUES}},
+B.prototype.onExecute=function(){var a=this.getInputData(0);if((a||this._temp_texture)&&this.isOutputConnected(0)&&a&&a.texture_type===GL.TEXTURE_2D)if(1>this.properties.iterations)this.setOutputData(0,a);else{var c=B._shader;c||(B._shader=c=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,B.pixel_shader));var d=a.width|0,f=a.height|0,g=a.type;this.properties.precision===b.LOW?g=gl.UNSIGNED_BYTE:this.properties.precision===b.HIGH&&(g=gl.HIGH_PRECISION_FORMAT);var e=this.properties.iterations||1,k=a,h=
+null,n=[],a={type:g,format:a.format},g=vec2.create(),s={u_offset:g};this._texture&&GL.Texture.releaseTemporary(this._texture);for(var l=0;l>1||0;f=f>>1||0;h=GL.Texture.getTemporary(d,f,a);n.push(h);k.setParameter(GL.TEXTURE_MAG_FILTER,GL.NEAREST);k.copyTo(h,c,s);if(1==d&&1==f)break;k=h}this._texture=n.pop();for(l=0;l>=2,d++,1!=b););a.copyTo(this._textures_chain[0]);for(var d=1;d<=this._textures_chain.length;++d)a=this._textures_chain[d];var f=e._shader,g=this._uniforms;g.u_mipmap_offset=this.properties.mipmap_offset;gl.disable(gl.DEPTH_TEST);
+gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){a.toViewport(f,g)})}},e.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tuniform mat4 u_samples_a;\n\t\tuniform mat4 u_samples_b;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_mipmap_offset;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 color = vec4(0.0);\n\t\t\t//random average\n\t\t\tfor(int i = 0; i < 4; ++i)\n\t\t\t\tfor(int j = 0; j < 4; ++j)\n\t\t\t\t{\n\t\t\t\t\tcolor += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t\tcolor += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\t\t\t\t}\n\t\t gl_FragColor = color * 0.03125;\n\t\t}\n\t\t",
+C.title="Smooth",C.desc="Smooth texture over time",C.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){C._shader||(C._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,C.pixel_shader));var c=this._temp_texture;c&&c.type==a.type&&c.width==a.width&&c.height==a.height||(c={type:a.type,format:gl.RGBA,filter:gl.NEAREST},this._temp_texture=new GL.Texture(a.width,a.height,c),this._temp_texture2=new GL.Texture(a.width,a.height,c),a.copyTo(this._temp_texture2));var c=
+this._temp_texture,b=this._temp_texture2,d=C._shader,f=this._uniforms;f.u_factor=1-this.getInputOrProperty("factor");gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);c.drawTo(function(){b.bind(1);a.toViewport(d,f)});this.setOutputData(0,c);this._temp_texture=b;this._temp_texture2=c}},C.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_factor;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tgl_FragColor = mix( texture2D( u_texture, v_coord ), texture2D( u_textureB, v_coord ), u_factor );\n\t\t}\n\t\t",
+F.registerNodeType("texture/temporal_smooth",C),r.title="Lineal Avg Smooth",r.desc="Smooth texture linearly over time",r["@samples"]={type:"number",min:1,max:64,step:1,precision:1},r.prototype.getPreviewTexture=function(){return this._temp_texture2},r.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){r._shader||(r._shader_copy=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,r.pixel_shader_copy),r._shader_avg=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,r.pixel_shader_avg));
+var c=Math.clamp(this.properties.samples,0,64),b=this.frame,d=this.properties.frames_interval;if(0==d||0==b%d){b=this._temp_texture;b&&b.type==a.type&&b.width==c||(b={type:a.type,format:gl.RGBA,filter:gl.NEAREST},this._temp_texture=new GL.Texture(c,1,b),this._temp_texture2=new GL.Texture(c,1,b),this._temp_texture_out=new GL.Texture(1,1,b));var f=this._temp_texture,g=this._temp_texture2,e=r._shader_copy,k=r._shader_avg,h=this._uniforms;h.u_samples=c;h.u_isamples=1/c;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);
+f.drawTo(function(){g.bind(1);a.toViewport(e,h)});this._temp_texture_out.drawTo(function(){f.toViewport(k,h)});this.setOutputData(0,this._temp_texture_out);this._temp_texture=g;this._temp_texture2=f}else this.setOutputData(0,this._temp_texture_out);this.setOutputData(1,this._temp_texture2);this.frame++}},r.pixel_shader_copy="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_isamples;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tif( v_coord.x <= u_isamples )\n\t\t\t\tgl_FragColor = texture2D( u_texture, vec2(0.5) );\n\t\t\telse\n\t\t\t\tgl_FragColor = texture2D( u_textureB, v_coord - vec2(u_isamples,0.0) );\n\t\t}\n\t\t",
+r.pixel_shader_avg="precision highp float;\n\t\tprecision highp float;\n\t\tuniform sampler2D u_texture;\n\t\tuniform int u_samples;\n\t\tuniform float u_isamples;\n\t\tvarying vec2 v_coord;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 color = vec4(0.0);\n\t\t\tfor(int i = 0; i < 64; ++i)\n\t\t\t{\n\t\t\t\tcolor += texture2D( u_texture, vec2( float(i)*u_isamples,0.0) );\n\t\t\t\tif(i == (u_samples - 1))\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgl_FragColor = color * u_isamples;\n\t\t}\n\t\t",F.registerNodeType("texture/linear_avg_smooth",
+r),A.title="Image to Texture",A.desc="Uploads an image to the GPU",A.prototype.onExecute=function(){var a=this.getInputData(0);if(a){var c=a.videoWidth||a.width,b=a.videoHeight||a.height;if(a.gltexture)this.setOutputData(0,a.gltexture);else{var d=this._temp_texture;d&&d.width==c&&d.height==b||(this._temp_texture=new GL.Texture(c,b,{format:gl.RGBA,filter:gl.LINEAR}));try{this._temp_texture.uploadImage(a)}catch(f){console.error("image comes from an unsafe location, cannot be uploaded to webgl: "+f);
+return}this.setOutputData(0,this._temp_texture)}}},F.registerNodeType("texture/imageToTexture",A),s.widgets_info={texture:{widget:"texture"},precision:{widget:"combo",values:b.MODE_VALUES}},s.title="LUT",s.desc="Apply LUT to Texture",s.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===b.PASS_THROUGH||!1===this.properties.enabled)this.setOutputData(0,a);else if(a){var c=this.getInputData(1);c||(c=b.getTexture(this.properties.texture));
+if(c){c.bind(0);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);gl.bindTexture(gl.TEXTURE_2D,null);var d=this.properties.intensity;this.isInputConnected(2)&&(this.properties.intensity=d=this.getInputData(2));this._tex=b.getTargetTexture(a,this._tex,this.properties.precision);this._tex.drawTo(function(){c.bind(1);a.toViewport(s._shader,{u_texture:0,u_textureB:1,
+u_amount:d})});this.setOutputData(0,this._tex)}else this.setOutputData(0,a)}}},s.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform float u_amount;\n\t\t\n\t\tvoid main() {\n\t\t\t lowp vec4 textureColor = clamp( texture2D(u_texture, v_coord), vec4(0.0), vec4(1.0) );\n\t\t\t mediump float blueColor = textureColor.b * 63.0;\n\t\t\t mediump vec2 quad1;\n\t\t\t quad1.y = floor(floor(blueColor) / 8.0);\n\t\t\t quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\t\t\t mediump vec2 quad2;\n\t\t\t quad2.y = floor(ceil(blueColor) / 8.0);\n\t\t\t quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\t\t\t highp vec2 texPos1;\n\t\t\t texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t texPos1.y = 1.0 - ((quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t highp vec2 texPos2;\n\t\t\t texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n\t\t\t texPos2.y = 1.0 - ((quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g));\n\t\t\t lowp vec4 newColor1 = texture2D(u_textureB, texPos1);\n\t\t\t lowp vec4 newColor2 = texture2D(u_textureB, texPos2);\n\t\t\t lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n\t\t\t gl_FragColor = vec4( mix( textureColor.rgb, newColor.rgb, u_amount), textureColor.w);\n\t\t}\n\t\t",
+F.registerNodeType("texture/LUT",s),n.title="Texture to Channels",n.desc="Split texture channels",n.prototype.onExecute=function(){var a=this.getInputData(0);if(a){this._channels||(this._channels=Array(4));for(var c=gl.RGB,b=0,d=0;4>d;d++)this.isOutputConnected(d)?(this._channels[d]&&this._channels[d].width==a.width&&this._channels[d].height==a.height&&this._channels[d].type==a.type&&this._channels[d].format==c||(this._channels[d]=new GL.Texture(a.width,a.height,{type:a.type,format:c,filter:gl.LINEAR})),
+b++):this._channels[d]=null;if(b){gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);for(var f=Mesh.getScreenQuad(),g=n._shader,e=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],d=0;4>d;d++)this._channels[d]&&(this._channels[d].drawTo(function(){a.bind(0);g.uniforms({u_texture:0,u_mask:e[d]}).draw(f)}),this.setOutputData(d,this._channels[d]))}}},n.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec4 u_mask;\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = vec4( vec3( length( texture2D(u_texture, v_coord) * u_mask )), 1.0 );\n\t\t}\n\t\t",
+F.registerNodeType("texture/textureChannels",n),t.title="Channels to Texture",t.desc="Split texture channels",t.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES}},t.prototype.onExecute=function(){var a=b.getWhiteTexture(),c=this.getInputData(0)||a,d=this.getInputData(1)||a,f=this.getInputData(2)||a,g=this.getInputData(3)||a;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad();t._shader||(t._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,t.pixel_shader));var k=t._shader,
+a=Math.max(c.width,d.width,f.width,g.width),h=Math.max(c.height,d.height,f.height,g.height),n=this.properties.precision==b.HIGH?b.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._texture&&this._texture.width==a&&this._texture.height==h&&this._texture.type==n||(this._texture=new GL.Texture(a,h,{type:n,format:gl.RGBA,filter:gl.LINEAR}));a=this._color;a[0]=this.properties.R;a[1]=this.properties.G;a[2]=this.properties.B;a[3]=this.properties.A;var s=this._uniforms;this._texture.drawTo(function(){c.bind(0);
+d.bind(1);f.bind(2);g.bind(3);k.uniforms(s).draw(e)});this.setOutputData(0,this._texture)},t.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_textureR;\n\t\tuniform sampler2D u_textureG;\n\t\tuniform sampler2D u_textureB;\n\t\tuniform sampler2D u_textureA;\n\t\tuniform vec4 u_color;\n\t\t\n\t\tvoid main() {\n\t\t gl_FragColor = u_color * vec4( \t\t\t\t\ttexture2D(u_textureR, v_coord).r,\t\t\t\t\ttexture2D(u_textureG, v_coord).r,\t\t\t\t\ttexture2D(u_textureB, v_coord).r,\t\t\t\t\ttexture2D(u_textureA, v_coord).r);\n\t\t}\n\t\t",
+F.registerNodeType("texture/channelsTexture",t),k.title="Color",k.desc="Generates a 1x1 texture with a constant color",k.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES}},k.prototype.onDrawBackground=function(a){var c=this.properties.color;a.fillStyle="rgb("+Math.floor(255*Math.clamp(c[0],0,1))+","+Math.floor(255*Math.clamp(c[1],0,1))+","+Math.floor(255*Math.clamp(c[2],0,1))+")";this.flags.collapsed?this.boxcolor=a.fillStyle:a.fillRect(0,0,this.size[0],this.size[1])},k.prototype.onExecute=
+function(){var a=this.properties.precision==b.HIGH?b.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._tex&&this._tex.type==a||(this._tex=new GL.Texture(1,1,{format:gl.RGBA,type:a,minFilter:gl.NEAREST}));a=this.properties.color;if(this.inputs)for(var c=0;ca.width?d:
+a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var e=Mesh.getScreenQuad(),k=null,h=this._uniforms;f?(k=c._shader_tex,k||(k=c._shader_tex=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,c.pixel_shader,{MIX_TEX:""}))):(k=c._shader_factor,k||(k=c._shader_factor=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,c.pixel_shader)),g=null==g?this.properties.factor:g,h.u_mix.set([g,g,g,g]));var n=this.properties.invert;this._tex.drawTo(function(){a.bind(n?1:0);d.bind(n?0:1);f&&f.bind(2);
+k.uniforms(h).draw(e)});this.setOutputData(0,this._tex)}}},c.prototype.onGetInputs=function(){return[["factor","number"]]},c.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_textureA;\n\t\tuniform sampler2D u_textureB;\n\t\t#ifdef MIX_TEX\n\t\t\tuniform sampler2D u_textureMix;\n\t\t#else\n\t\t\tuniform vec4 u_mix;\n\t\t#endif\n\t\t\n\t\tvoid main() {\n\t\t\t#ifdef MIX_TEX\n\t\t\t vec4 f = texture2D(u_textureMix, v_coord);\n\t\t\t#else\n\t\t\t vec4 f = u_mix;\n\t\t\t#endif\n\t\t gl_FragColor = mix( texture2D(u_textureA, v_coord), texture2D(u_textureB, v_coord), f );\n\t\t}\n\t\t",
+F.registerNodeType("texture/mix",c),d.title="Edges",d.desc="Detects edges",d.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES}},d.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===b.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=b.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var c=Mesh.getScreenQuad(),f=d._shader,g=this.properties.invert,e=this.properties.factor,
+k=this.properties.threshold?1:0;this._tex.drawTo(function(){a.bind(0);f.uniforms({u_texture:0,u_isize:[1/a.width,1/a.height],u_factor:e,u_threshold:k,u_invert:g?1:0}).draw(c)});this.setOutputData(0,this._tex)}}},d.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_isize;\n\t\tuniform int u_invert;\n\t\tuniform float u_factor;\n\t\tuniform float u_threshold;\n\t\t\n\t\tvoid main() {\n\t\t\tvec4 center = texture2D(u_texture, v_coord);\n\t\t\tvec4 up = texture2D(u_texture, v_coord + u_isize * vec2(0.0,1.0) );\n\t\t\tvec4 down = texture2D(u_texture, v_coord + u_isize * vec2(0.0,-1.0) );\n\t\t\tvec4 left = texture2D(u_texture, v_coord + u_isize * vec2(1.0,0.0) );\n\t\t\tvec4 right = texture2D(u_texture, v_coord + u_isize * vec2(-1.0,0.0) );\n\t\t\tvec4 diff = abs(center - up) + abs(center - down) + abs(center - left) + abs(center - right);\n\t\t\tdiff *= u_factor;\n\t\t\tif(u_invert == 1)\n\t\t\t\tdiff.xyz = vec3(1.0) - diff.xyz;\n\t\t\tif( u_threshold == 0.0 )\n\t\t\t\tgl_FragColor = vec4( diff.xyz, center.a );\n\t\t\telse\n\t\t\t\tgl_FragColor = vec4( diff.x > 0.5 ? 1.0 : 0.0, diff.y > 0.5 ? 1.0 : 0.0, diff.z > 0.5 ? 1.0 : 0.0, center.a );\n\t\t}\n\t\t",
+F.registerNodeType("texture/edges",d),g.title="Depth Range",g.desc="Generates a texture with a depth range",g.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(a){var c=gl.UNSIGNED_BYTE;this.properties.high_precision&&(c=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==c&&this._temp_texture.width==a.width&&this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:c,format:gl.RGBA,
+filter:gl.LINEAR}));var b=this._uniforms,c=this.properties.distance;this.isInputConnected(1)&&(c=this.getInputData(1),this.properties.distance=c);var d=this.properties.range;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.range=d);b.u_distance=c;b.u_range=d;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var f=Mesh.getScreenQuad();g._shader||(g._shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,g.pixel_shader),g._shader_onlydepth=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,g.pixel_shader,
+{ONLY_DEPTH:""}));var e=this.properties.only_depth?g._shader_onlydepth:g._shader,c=null,c=a.near_far_planes?a.near_far_planes:window.LS&&LS.Renderer._main_camera?LS.Renderer._main_camera._uniforms.u_camera_planes:[0.1,1E3];b.u_camera_planes=c;this._temp_texture.drawTo(function(){a.bind(0);e.uniforms(b).draw(f)});this._temp_texture.near_far_planes=c;this.setOutputData(0,this._temp_texture)}}},g.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec2 u_camera_planes;\n\t\tuniform float u_distance;\n\t\tuniform float u_range;\n\t\t\n\t\tfloat LinearDepth()\n\t\t{\n\t\t\tfloat zNear = u_camera_planes.x;\n\t\t\tfloat zFar = u_camera_planes.y;\n\t\t\tfloat depth = texture2D(u_texture, v_coord).x;\n\t\t\tdepth = depth * 2.0 - 1.0;\n\t\t\treturn zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\t\t}\n\t\t\n\t\tvoid main() {\n\t\t\tfloat depth = LinearDepth();\n\t\t\t#ifdef ONLY_DEPTH\n\t\t\t gl_FragColor = vec4(depth);\n\t\t\t#else\n\t\t\t\tfloat diff = abs(depth * u_camera_planes.y - u_distance);\n\t\t\t\tfloat dof = 1.0;\n\t\t\t\tif(diff <= u_range)\n\t\t\t\t\tdof = diff / u_range;\n\t\t\t gl_FragColor = vec4(dof);\n\t\t\t#endif\n\t\t}\n\t\t",
+F.registerNodeType("texture/depth_range",g),f.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES}},f.title="Linear Depth",f.desc="Creates a color texture with linear depth",f.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(a&&(a.format==gl.DEPTH_COMPONENT||a.format==gl.DEPTH_STENCIL)){var c=this.properties.precision==b.HIGH?gl.HIGH_PRECISION_FORMAT:gl.UNSIGNED_BYTE;this._temp_texture&&this._temp_texture.type==c&&this._temp_texture.width==a.width&&
+this._temp_texture.height==a.height||(this._temp_texture=new GL.Texture(a.width,a.height,{type:c,format:gl.RGB,filter:gl.LINEAR}));var d=this._uniforms;d.u_near=a.near_far_planes[0];d.u_far=a.near_far_planes[1];d.u_invert=this.properties.invert?1:0;gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var g=Mesh.getScreenQuad();f._shader||(f._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,f.pixel_shader));var e=f._shader,c=null,c=a.near_far_planes?a.near_far_planes:window.LS&&LS.Renderer._main_camera?
+LS.Renderer._main_camera._uniforms.u_camera_planes:[0.1,1E3];d.u_camera_planes=c;this._temp_texture.drawTo(function(){a.bind(0);e.uniforms(d).draw(g)});this._temp_texture.near_far_planes=c;this.setOutputData(0,this._temp_texture)}}},f.pixel_shader="precision highp float;\n\t\tprecision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform float u_near;\n\t\tuniform float u_far;\n\t\tuniform int u_invert;\n\t\t\n\t\tvoid main() {\n\t\t\tfloat zNear = u_near;\n\t\t\tfloat zFar = u_far;\n\t\t\tfloat depth = texture2D(u_texture, v_coord).x;\n\t\t\tdepth = depth * 2.0 - 1.0;\n\t\t\tfloat f = zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\t\t\tif( u_invert == 1 )\n\t\t\t\tf = 1.0 - f;\n\t\t\tgl_FragColor = vec4(vec3(f),1.0);\n\t\t}\n\t\t",
+F.registerNodeType("texture/linear_depth",f),K.title="Blur",K.desc="Blur a texture",K.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES}},K.max_iterations=20,K.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var c=this._final_texture;c&&c.width==a.width&&c.height==a.height&&c.type==a.type||(c=this._final_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));var b=this.properties.iterations;this.isInputConnected(1)&&
+(b=this.getInputData(1),this.properties.iterations=b);b=Math.min(Math.floor(b),K.max_iterations);if(0==b)this.setOutputData(0,a);else{var d=this.properties.intensity;this.isInputConnected(2)&&(d=this.getInputData(2),this.properties.intensity=d);var f=F.camera_aspect;f||void 0===window.gl||(f=gl.canvas.height/gl.canvas.width);f||(f=1);var f=this.properties.preserve_aspect?f:1,g=this.properties.scale||[1,1];a.applyBlur(f*g[0],g[1],d,c);for(a=1;a>=1;1<(d|0)&&(d>>=1);if(2>c)break;n=k[m]=GL.Texture.getTemporary(c,d,f);p[0]=1/s.width;p[1]=1/s.height;s.blit(n,h.uniforms(e));s=n}this.isOutputConnected(2)&&(c=this._average_texture,c&&c.type==a.type&&c.format==a.format||(c=this._average_texture=new GL.Texture(1,1,{type:a.type,format:a.format,filter:gl.LINEAR})),p[0]=1/s.width,p[1]=1/s.height,e.u_intensity=q,e.u_delta=1,s.blit(c,h.uniforms(e)),this.setOutputData(2,c));gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);e.u_intensity=
+this.getInputOrProperty("persistence");e.u_delta=0.5;for(m-=2;0<=m;m--)n=k[m],k[m]=null,p[0]=1/s.width,p[1]=1/s.height,s.blit(n,h.uniforms(e)),GL.Texture.releaseTemporary(s),s=n;gl.disable(gl.BLEND);this.isOutputConnected(1)&&(k=this._glow_texture,k&&k.width==a.width&&k.height==a.height&&k.type==g&&k.format==a.format||(k=this._glow_texture=new GL.Texture(a.width,a.height,{type:g,format:a.format,filter:gl.LINEAR})),s.blit(k),this.setOutputData(1,k));if(this.isOutputConnected(0)){k=this._final_texture;
+k&&k.width==a.width&&k.height==a.height&&k.type==g&&k.format==a.format||(k=this._final_texture=new GL.Texture(a.width,a.height,{type:g,format:a.format,filter:gl.LINEAR}));var t=this.getInputData(1),r=this.getInputOrProperty("dirt_factor");e.u_intensity=q;h=t?x._dirt_final_shader:x._final_shader;h||(h=t?x._dirt_final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,x.final_pixel_shader,{USE_DIRT:""}):x._final_shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,x.final_pixel_shader));k.drawTo(function(){a.bind(0);
+s.bind(1);t&&(h.setUniform("u_dirt_factor",r),h.setUniform("u_dirt_texture",t.bind(2)));h.toViewport(e)});this.setOutputData(0,k)}GL.Texture.releaseTemporary(s)}},x.cut_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform float u_threshold;\n\tvoid main() {\n\t\tgl_FragColor = max( texture2D( u_texture, v_coord ) - vec4( u_threshold ), vec4(0.0) );\n\t}",x.scale_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform vec2 u_texel_size;\n\tuniform float u_delta;\n\tuniform float u_intensity;\n\t\n\tvec4 sampleBox(vec2 uv) {\n\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\tvec4 s = texture2D( u_texture, uv + o.xy ) + texture2D( u_texture, uv + o.zy) + texture2D( u_texture, uv + o.xw) + texture2D( u_texture, uv + o.zw);\n\t\treturn s * 0.25;\n\t}\n\tvoid main() {\n\t\tgl_FragColor = u_intensity * sampleBox( v_coord );\n\t}",
+x.final_pixel_shader="precision highp float;\n\tvarying vec2 v_coord;\n\tuniform sampler2D u_texture;\n\tuniform sampler2D u_glow_texture;\n\t#ifdef USE_DIRT\n\t\tuniform sampler2D u_dirt_texture;\n\t#endif\n\tuniform vec2 u_texel_size;\n\tuniform float u_delta;\n\tuniform float u_intensity;\n\tuniform float u_dirt_factor;\n\t\n\tvec4 sampleBox(vec2 uv) {\n\t\tvec4 o = u_texel_size.xyxy * vec2(-u_delta, u_delta).xxyy;\n\t\tvec4 s = texture2D( u_glow_texture, uv + o.xy ) + texture2D( u_glow_texture, uv + o.zy) + texture2D( u_glow_texture, uv + o.xw) + texture2D( u_glow_texture, uv + o.zw);\n\t\treturn s * 0.25;\n\t}\n\tvoid main() {\n\t\tvec4 glow = sampleBox( v_coord );\n\t\t#ifdef USE_DIRT\n\t\t\tglow = mix( glow, glow * texture2D( u_dirt_texture, v_coord ), u_dirt_factor );\n\t\t#endif\n\t\tgl_FragColor = texture2D( u_texture, v_coord ) + u_intensity * glow;\n\t}",
+F.registerNodeType("texture/glow",x),H.title="Kuwahara Filter",H.desc="Filters a texture giving an artistic oil canvas painting",H.max_radius=10,H._shaders=[],H.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var c=this._temp_texture;c&&c.width==a.width&&c.height==a.height&&c.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));c=this.properties.radius;c=Math.min(Math.floor(c),H.max_radius);if(0==
+c)this.setOutputData(0,a);else{var b=this.properties.intensity,d=F.camera_aspect;d||void 0===window.gl||(d=gl.canvas.height/gl.canvas.width);d||(d=1);d=this.properties.preserve_aspect?d:1;H._shaders[c]||(H._shaders[c]=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,H.pixel_shader,{RADIUS:c.toFixed(0)}));var f=H._shaders[c],g=GL.Mesh.getScreenQuad();a.bind(0);this._temp_texture.drawTo(function(){f.uniforms({u_texture:0,u_intensity:b,u_resolution:[a.width,a.height],u_iResolution:[1/a.width,1/a.height]}).draw(g)});
+this.setOutputData(0,this._temp_texture)}}},H.pixel_shader="\nprecision highp float;\nvarying vec2 v_coord;\nuniform sampler2D u_texture;\nuniform float u_intensity;\nuniform vec2 u_resolution;\nuniform vec2 u_iResolution;\n#ifndef RADIUS\n\t#define RADIUS 7\n#endif\nvoid main() {\n\n\tconst int radius = RADIUS;\n\tvec2 fragCoord = v_coord;\n\tvec2 src_size = u_iResolution;\n\tvec2 uv = v_coord;\n\tfloat n = float((radius + 1) * (radius + 1));\n\tint i;\n\tint j;\n\tvec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0);\n\tvec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0);\n\tvec3 c;\n\t\n\tfor (int j = -radius; j <= 0; ++j) {\n\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm0 += c;\n\t\t\ts0 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = -radius; j <= 0; ++j) {\n\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm1 += c;\n\t\t\ts1 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = 0; j <= radius; ++j) {\n\t\tfor (int i = 0; i <= radius; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm2 += c;\n\t\t\ts2 += c * c;\n\t\t}\n\t}\n\t\n\tfor (int j = 0; j <= radius; ++j) {\n\t\tfor (int i = -radius; i <= 0; ++i) {\n\t\t\tc = texture2D(u_texture, uv + vec2(i,j) * src_size).rgb;\n\t\t\tm3 += c;\n\t\t\ts3 += c * c;\n\t\t}\n\t}\n\t\n\tfloat min_sigma2 = 1e+2;\n\tm0 /= n;\n\ts0 = abs(s0 / n - m0 * m0);\n\t\n\tfloat sigma2 = s0.r + s0.g + s0.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m0, 1.0);\n\t}\n\t\n\tm1 /= n;\n\ts1 = abs(s1 / n - m1 * m1);\n\t\n\tsigma2 = s1.r + s1.g + s1.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m1, 1.0);\n\t}\n\t\n\tm2 /= n;\n\ts2 = abs(s2 / n - m2 * m2);\n\t\n\tsigma2 = s2.r + s2.g + s2.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m2, 1.0);\n\t}\n\t\n\tm3 /= n;\n\ts3 = abs(s3 / n - m3 * m3);\n\t\n\tsigma2 = s3.r + s3.g + s3.b;\n\tif (sigma2 < min_sigma2) {\n\t\tmin_sigma2 = sigma2;\n\t\tgl_FragColor = vec4(m3, 1.0);\n\t}\n}\n",
+F.registerNodeType("texture/kuwahara",H),I.title="XDoG Filter",I.desc="Filters a texture giving an artistic ink style",I.max_radius=10,I._shaders=[],I.prototype.onExecute=function(){var a=this.getInputData(0);if(a&&this.isOutputConnected(0)){var c=this._temp_texture;c&&c.width==a.width&&c.height==a.height&&c.type==a.type||(this._temp_texture=new GL.Texture(a.width,a.height,{type:a.type,format:gl.RGBA,filter:gl.LINEAR}));I._xdog_shader||(I._xdog_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,I.xdog_pixel_shader));
+var d=I._xdog_shader,b=GL.Mesh.getScreenQuad(),f=this.properties.sigma,g=this.properties.k,e=this.properties.p,k=this.properties.epsilon,h=this.properties.phi;a.bind(0);this._temp_texture.drawTo(function(){d.uniforms({src:0,sigma:f,k:g,p:e,epsilon:k,phi:h,cvsWidth:a.width,cvsHeight:a.height}).draw(b)});this.setOutputData(0,this._temp_texture)}},I.xdog_pixel_shader="\nprecision highp float;\nuniform sampler2D src;\n\nuniform float cvsHeight;\nuniform float cvsWidth;\n\nuniform float sigma;\nuniform float k;\nuniform float p;\nuniform float epsilon;\nuniform float phi;\nvarying vec2 v_coord;\n\nfloat cosh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat cosH = (tmp + 1.0 / tmp) / 2.0;\n\treturn cosH;\n}\n\nfloat tanh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat tanH = (tmp - 1.0 / tmp) / (tmp + 1.0 / tmp);\n\treturn tanH;\n}\n\nfloat sinh(float val)\n{\n\tfloat tmp = exp(val);\n\tfloat sinH = (tmp - 1.0 / tmp) / 2.0;\n\treturn sinH;\n}\n\nvoid main(void){\n\tvec3 destColor = vec3(0.0);\n\tfloat tFrag = 1.0 / cvsHeight;\n\tfloat sFrag = 1.0 / cvsWidth;\n\tvec2 Frag = vec2(sFrag,tFrag);\n\tvec2 uv = gl_FragCoord.st;\n\tfloat twoSigmaESquared = 2.0 * sigma * sigma;\n\tfloat twoSigmaRSquared = twoSigmaESquared * k * k;\n\tint halfWidth = int(ceil( 1.0 * sigma * k ));\n\n\tconst int MAX_NUM_ITERATION = 99999;\n\tvec2 sum = vec2(0.0);\n\tvec2 norm = vec2(0.0);\n\n\tfor(int cnt=0;cnt (2*halfWidth+1)*(2*halfWidth+1)){break;}\n\t\tint i = int(cnt / (2*halfWidth+1)) - halfWidth;\n\t\tint j = cnt - halfWidth - int(cnt / (2*halfWidth+1)) * (2*halfWidth+1);\n\n\t\tfloat d = length(vec2(i,j));\n\t\tvec2 kernel = vec2( exp( -d * d / twoSigmaESquared ), \n\t\t\t\t\t\t\texp( -d * d / twoSigmaRSquared ));\n\n\t\tvec2 L = texture2D(src, (uv + vec2(i,j)) * Frag).xx;\n\n\t\tnorm += kernel;\n\t\tsum += kernel * L;\n\t}\n\n\tsum /= norm;\n\n\tfloat H = 100.0 * ((1.0 + p) * sum.x - p * sum.y);\n\tfloat edge = ( H > epsilon )? 1.0 : 1.0 + tanh( phi * (H - epsilon));\n\tdestColor = vec3(edge);\n\tgl_FragColor = vec4(destColor, 1.0);\n}",
+F.registerNodeType("texture/xDoG",I),G.title="Webcam",G.desc="Webcam texture",G.is_webcam_open=!1,G.prototype.openStream=function(){function a(d){G.is_webcam_open=!1;console.log("Webcam rejected",d);c._webcam_stream=!1;c.boxcolor="red";c.trigger("stream_error")}if(navigator.getUserMedia){this._waiting_confirmation=!0;navigator.mediaDevices.getUserMedia({audio:!1,video:{facingMode:this.properties.facingMode}}).then(this.streamReady.bind(this))["catch"](a);var c=this}},G.prototype.closeStream=function(){if(this._webcam_stream){var a=
+this._webcam_stream.getTracks();if(a.length)for(var c=0;c=this.size[1]||!this._video||(a.save(),a.webgl?this._video_texture&&a.drawImage(this._video_texture,0,0,this.size[0],this.size[1]):a.drawImage(this._video,
+0,0,this.size[0],this.size[1]),a.restore())},G.prototype.onExecute=function(){null!=this._webcam_stream||this._waiting_confirmation||this.openStream();if(this._video&&this._video.videoWidth){var a=this._video.videoWidth,c=this._video.videoHeight,d=this._video_texture;d&&d.width==a&&d.height==c||(this._video_texture=new GL.Texture(a,c,{format:gl.RGB,filter:gl.LINEAR}));this._video_texture.uploadImage(this._video);this._video_texture.version=++this.version;this.properties.texture_name&&(b.getTexturesContainer()[this.properties.texture_name]=
+this._video_texture);this.setOutputData(0,this._video_texture);for(a=1;aMath.abs(d))return b[1];d=(a-b[0])/d;return b[1]*(1-d)+f[1]*d}}return 0}},u.prototype.updateCurve=function(){for(var a=this._values,c=a.length/4,d=this.properties.split_channels,b=0;b= res)\n\t\t\t\t\tbreak;\n\t\t\t\tiCount++;\n\t\t\t}\n\t\t\tfloat nf = n/normK;\n\t\t\treturn nf*nf*nf*nf;\n\t\t}\n\t\tvoid main() {\n\t\t\tvec2 uv = v_coord * u_scale * u_viewport + u_offset * u_scale;\n\t\t\tvec4 color = vec4( pNoise( uv, u_octaves ) * u_amplitude );\n\t\t\tgl_FragColor = color;\n\t\t}",
+F.registerNodeType("texture/perlin",L),N.title="Canvas2D",N.desc="Executes Canvas2D code inside a texture or the viewport.",N.help="Set width and height to 0 to match viewport size.",N.widgets_info={precision:{widget:"combo",values:b.MODE_VALUES},code:{type:"code"},width:{type:"Number",precision:0,step:1},height:{type:"Number",precision:0,step:1}},N.prototype.onPropertyChanged=function(a,c){"code"==a&&this.compileCode(c)},N.prototype.compileCode=function(a){this._func=null;if(F.allow_scripts)try{this._func=
+new Function("canvas","ctx","time","script","v",a),this.boxcolor="#00FF00"}catch(c){this.boxcolor="#FF0000",console.error("Error parsing script"),console.error(c)}},N.prototype.onExecute=function(){var a=this._func;a&&this.isOutputConnected(0)&&this.executeDraw(a)},N.prototype.executeDraw=function(a){var c=this.properties.width||gl.canvas.width,d=this.properties.height||gl.canvas.height,f=this._temp_texture,g=b.getTextureType(this.properties.precision);f&&f.width==c&&f.height==d&&f.type==g||(f=this._temp_texture=
+new GL.Texture(c,d,{format:gl.RGBA,filter:gl.LINEAR,type:g}));var e=this.getInputData(0),k=this.properties,h=this,n=this.graph.getTime(),s=gl,l=gl.canvas;if(this.properties.use_html_canvas||!z.enableWebGLCanvas)this._canvas?(l=this._canvas,s=this._ctx):(l=this._canvas=createCanvas(c.height),s=this._ctx=l.getContext("2d")),l.width=c,l.height=d;if(s==gl)f.drawTo(function(){gl.start2D();k.clear&&(gl.clearColor(0,0,0,0),gl.clear(gl.COLOR_BUFFER_BIT));try{a.draw?a.draw.call(h,l,s,n,a,e):a.call(h,l,s,n,
+a,e),h.boxcolor="#00FF00"}catch(c){h.boxcolor="#FF0000",console.error("Error executing script"),console.error(c)}gl.finish2D()});else{k.clear&&s.clearRect(0,0,l.width,l.height);try{a.draw?a.draw.call(this,l,s,n,a,e):a.call(this,l,s,n,a,e),this.boxcolor="#00FF00"}catch(p){this.boxcolor="#FF0000",console.error("Error executing script"),console.error(p)}f.uploadImage(l)}this.setOutputData(0,f)},F.registerNodeType("texture/canvas2D",N),O.title="Matte",O.desc="Extracts background",O.widgets_info={key_color:{widget:"color"},
+precision:{widget:"combo",values:b.MODE_VALUES}},O.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(this.properties.precision===b.PASS_THROUGH)this.setOutputData(0,a);else if(a){this._tex=b.getTargetTexture(a,this._tex,this.properties.precision);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);this._uniforms||(this._uniforms={u_texture:0,u_key_color:this.properties.key_color,u_threshold:1,u_slope:1});var c=this._uniforms,d=Mesh.getScreenQuad(),f=O._shader;f||
+(f=O._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,O.pixel_shader));c.u_key_color=this.properties.key_color;c.u_threshold=this.properties.threshold;c.u_slope=this.properties.slope;this._tex.drawTo(function(){a.bind(0);f.uniforms(c).draw(d)});this.setOutputData(0,this._tex)}}},O.pixel_shader="precision highp float;\n\t\tvarying vec2 v_coord;\n\t\tuniform sampler2D u_texture;\n\t\tuniform vec3 u_key_color;\n\t\tuniform float u_threshold;\n\t\tuniform float u_slope;\n\t\t\n\t\tvoid main() {\n\t\t\tvec3 color = texture2D( u_texture, v_coord ).xyz;\n\t\t\tfloat diff = length( normalize(color) - normalize(u_key_color) );\n\t\t\tfloat edge = u_threshold * (1.0 - u_slope);\n\t\t\tfloat alpha = smoothstep( edge, u_threshold, diff);\n\t\t\tgl_FragColor = vec4( color, alpha );\n\t\t}",
+F.registerNodeType("texture/matte",O),P.title="CubemapToTexture2D",P.desc="Transforms a CUBEMAP texture into a TEXTURE2D in Polar Representation",P.prototype.onExecute=function(){if(this.isOutputConnected(0)){var a=this.getInputData(0);if(a&&a.texture_type==GL.TEXTURE_CUBE_MAP){!this._last_tex||this._last_tex.height==a.height&&this._last_tex.type==a.type||(this._last_tex=null);var c=this.getInputOrProperty("yaw");this._last_tex=GL.Texture.cubemapToTexture2D(a,a.height,this._last_tex,!0,c);this.setOutputData(0,
+this._last_tex)}}},F.registerNodeType("texture/cubemapToTexture2D",P))})(this);
+(function(z){function b(){return 1E5*Math.random()|0}function m(){this.addInput("obj","");this.addInput("radius","number");this.addOutput("out","geometry");this.addOutput("points","[vec3]");this.properties={radius:1,num_points:4096,generate_normals:!0,regular:!1,mode:m.SPHERE,force_update:!1};this.points=new Float32Array(3*this.properties.num_points);this.normals=new Float32Array(3*this.properties.num_points);this.must_update=!0;this.version=0;var a=this;this.addWidget("button","update",null,function(){a.must_update=
+!0});this.geometry={vertices:null,_id:b()};this._last_radius=this._old_obj=null}function q(a,d){var b=a.length,f=0,e=0,k=b;if(0==b)return-1;if(1==b)return 0;for(;k>=f;){e=0.5*(k+f)|0;b=a[e];if(b==d)break;if(f==k-1)return f;b
+a&&(a=1);this.points&&this.points.length==3*a||(this.points=new Float32Array(3*a));this.properties.generate_normals?this.normals&&this.normals.length==this.points.length||(this.normals=new Float32Array(this.points.length)):this.normals=null;var d=this._last_radius||this.properties.radius,b=this.properties.mode,f=this.getInputData(0);this._old_obj_version=f?f._version:null;this.points=m.generatePoints(d,a,b,this.points,this.normals,this.properties.regular,f);this.version++};m.generatePoints=function(a,
+d,b,f,e,k,h){var n=3*d;f&&f.length==n||(f=new Float32Array(n));var s=new Float32Array(3),l=new Float32Array([0,1,0]);if(k)if(b==m.RECTANGLE){n=Math.floor(Math.sqrt(d));for(d=0;dk||rh&&hn))break}this.geometry.indices=this.indices=new Uint32Array(s)}this.indices&&this.indices.length?
+(this.geometry.indices=this.indices,this.setOutputData(0,this.geometry)):this.setOutputData(0,null)}};A.registerNodeType("geometry/connectPoints",w);"undefined"!=typeof GL&&(B.title="to geometry",B.desc="converts a mesh to geometry",B.prototype.onExecute=function(){var a=this.getInputData(0);if(a){if(a!=this.last_mesh){this.last_mesh=a;for(i in a.vertexBuffers)this.geometry[i]=a.vertexBuffers[i].data;a.indexBuffers.triangles&&(this.geometry.indices=a.indexBuffers.triangles.data);this.geometry._id=
+b();this.geometry._version=0}this.setOutputData(0,this.geometry);this.geometry&&this.setOutputData(1,this.geometry.vertices)}},A.registerNodeType("geometry/toGeometry",B),l.title="Geo to Mesh",l.prototype.updateMesh=function(a){this.mesh||(this.mesh=new GL.Mesh);for(var b in a)if("_"!=b[0]){var e=a[b],f=GL.Mesh.common_buffers[b];if(f||"indices"==b){var f=f?f.spacing:3,k=this.mesh.vertexBuffers[b];k&&k.data.length==e.length?(k.data.set(e),k.upload(GL.DYNAMIC_DRAW)):k=new GL.Buffer("indices"==b?GL.ELEMENT_ARRAY_BUFFER:
+GL.ARRAY_BUFFER,e,f,GL.DYNAMIC_DRAW);this.mesh.addBuffer(b,k)}}if(this.mesh.vertexBuffers.normals&&this.mesh.vertexBuffers.normals.data.length!=this.mesh.vertexBuffers.vertices.data.length){e=new Float32Array([0,1,0]);f=new Float32Array(this.mesh.vertexBuffers.vertices.data.length);for(b=0;b 0.45 )\n\t\t\t\t\t\tdiscard;\n\t\t\t\t#endif\n\t\t\t#endif\n\t\t\t#ifdef USE_COLOR\n\t\t\t\tcolor *= v_color;\n\t\t\t#endif\n\t\t\tgl_FragColor = color;\n\t\t}\t")})(this);
+(function(z){var b=z.LiteGraph;if("undefined"!=typeof GL){var m=function(){this.addInput("Texture","Texture");this.addInput("Aberration","number");this.addInput("Distortion","number");this.addInput("Blur","number");this.addOutput("Texture","Texture");this.properties={aberration:1,distortion:1,blur:1,precision:LGraphTexture.DEFAULT};m._shader||(m._shader=new GL.Shader(GL.Shader.SCREEN_VERTEX_SHADER,m.pixel_shader),m._texture=new GL.Texture(3,1,{format:gl.RGB,wrap:gl.CLAMP_TO_EDGE,magFilter:gl.LINEAR,
+minFilter:gl.LINEAR,pixel_data:[255,0,0,0,255,0,0,0,255]}))};m.title="Lens";m.desc="Camera Lens distortion";m.widgets_info={precision:{widget:"combo",values:LGraphTexture.MODE_VALUES}};m.prototype.onExecute=function(){var b=this.getInputData(0);if(this.properties.precision===LGraphTexture.PASS_THROUGH)this.setOutputData(0,b);else if(b){this._tex=LGraphTexture.getTargetTexture(b,this._tex,this.properties.precision);var p=this.properties.aberration;this.isInputConnected(1)&&(p=this.getInputData(1),
+this.properties.aberration=p);var q=this.properties.distortion;this.isInputConnected(2)&&(q=this.getInputData(2),this.properties.distortion=q);var w=this.properties.blur;this.isInputConnected(3)&&(w=this.getInputData(3),this.properties.blur=w);gl.disable(gl.BLEND);gl.disable(gl.DEPTH_TEST);var y=Mesh.getScreenQuad(),l=m._shader;this._tex.drawTo(function(){b.bind(0);l.uniforms({u_texture:0,u_aberration:p,u_distortion:q,u_blur:w}).draw(y)});this.setOutputData(0,this._tex)}};m.pixel_shader="precision highp float;\n\t\t\tprecision highp float;\n\t\t\tvarying vec2 v_coord;\n\t\t\tuniform sampler2D u_texture;\n\t\t\tuniform vec2 u_camera_planes;\n\t\t\tuniform float u_aberration;\n\t\t\tuniform float u_distortion;\n\t\t\tuniform float u_blur;\n\t\t\t\n\t\t\tvoid main() {\n\t\t\t\tvec2 coord = v_coord;\n\t\t\t\tfloat dist = distance(vec2(0.5), coord);\n\t\t\t\tvec2 dist_coord = coord - vec2(0.5);\n\t\t\t\tfloat percent = 1.0 + ((0.5 - dist) / 0.5) * u_distortion;\n\t\t\t\tdist_coord *= percent;\n\t\t\t\tcoord = dist_coord + vec2(0.5);\n\t\t\t\tvec4 color = texture2D(u_texture,coord, u_blur * dist);\n\t\t\t\tcolor.r = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0+0.01*u_aberration), u_blur * dist ).r;\n\t\t\t\tcolor.b = texture2D(u_texture,vec2(0.5) + dist_coord * (1.0-0.01*u_aberration), u_blur * dist ).b;\n\t\t\t\tgl_FragColor = color;\n\t\t\t}\n\t\t\t";
+b.registerNodeType("fx/lens",m);z.LGraphFXLens=m;var q=function(){this.addInput("Texture","Texture");this.addInput("Blurred","Texture");this.addInput("Mask","Texture");this.addInput("Threshold","number");this.addOutput("Texture","Texture");this.properties={shape:"",size:10,alpha:1,threshold:1,high_precision:!1}};q.title="Bokeh";q.desc="applies an Bokeh effect";q.widgets_info={shape:{widget:"texture"}};q.prototype.onExecute=function(){var b=this.getInputData(0),p=this.getInputData(1),m=this.getInputData(2);
+if(b&&m&&this.properties.shape){p||(p=b);var w=LGraphTexture.getTexture(this.properties.shape);if(w){var y=this.properties.threshold;this.isInputConnected(3)&&(y=this.getInputData(3),this.properties.threshold=y);var l=gl.UNSIGNED_BYTE;this.properties.high_precision&&(l=gl.half_float_ext?gl.HALF_FLOAT_OES:gl.FLOAT);this._temp_texture&&this._temp_texture.type==l&&this._temp_texture.width==b.width&&this._temp_texture.height==b.height||(this._temp_texture=new GL.Texture(b.width,b.height,{type:l,format:gl.RGBA,
+filter:gl.LINEAR}));var e=q._first_shader;e||(e=q._first_shader=new GL.Shader(Shader.SCREEN_VERTEX_SHADER,q._first_pixel_shader));var z=q._second_shader;z||(z=q._second_shader=new GL.Shader(q._second_vertex_shader,q._second_pixel_shader));var r=this._points_mesh;r&&r._width==b.width&&r._height==b.height&&2==r._spacing||(r=this.createPointsMesh(b.width,b.height,2));var A=Mesh.getScreenQuad(),s=this.properties.size,n=this.properties.alpha;gl.disable(gl.DEPTH_TEST);gl.disable(gl.BLEND);this._temp_texture.drawTo(function(){b.bind(0);
+p.bind(1);m.bind(2);e.uniforms({u_texture:0,u_texture_blur:1,u_mask:2,u_texsize:[b.width,b.height]}).draw(A)});this._temp_texture.drawTo(function(){gl.enable(gl.BLEND);gl.blendFunc(gl.ONE,gl.ONE);b.bind(0);w.bind(3);z.uniforms({u_texture:0,u_mask:2,u_shape:3,u_alpha:n,u_threshold:y,u_pointSize:s,u_itexsize:[1/b.width,1/b.height]}).draw(r,gl.POINTS)});this.setOutputData(0,this._temp_texture)}}else this.setOutputData(0,b)};q.prototype.createPointsMesh=function(b,p,m){for(var q=Math.round(b/m),y=Math.round(p/
+m),l=new Float32Array(q*y*2),e=-1,z=2/b*m,r=2/p*m,A=0;A=c.NOTEON||f<=c.NOTEOFF)this.channel=
-e&15};Object.defineProperty(c.prototype,"velocity",{get:function(){return this.cmd==c.NOTEON?this.data[2]:-1},set:function(c){this.data[2]=c},enumerable:!0});c.notes="A A# B C C# D D# E F F# G G#".split(" ");c.note_to_index={A:0,"A#":1,B:2,C:3,"C#":4,D:5,"D#":6,E:7,F:8,"F#":9,G:10,"G#":11};Object.defineProperty(c.prototype,"note",{get:function(){return this.cmd!=c.NOTEON?-1:c.toNoteString(this.data[1],!0)},set:function(c){throw"notes cannot be assigned this way, must modify the data[1]";},enumerable:!0});
-Object.defineProperty(c.prototype,"octave",{get:function(){return this.cmd!=c.NOTEON?-1:Math.floor((this.data[1]-24)/12+1)},set:function(c){throw"octave cannot be assigned this way, must modify the data[1]";},enumerable:!0});c.prototype.getPitch=function(){return 440*Math.pow(2,(this.data[1]-69)/12)};c.computePitch=function(c){return 440*Math.pow(2,(c-69)/12)};c.prototype.getCC=function(){return this.data[1]};c.prototype.getCCValue=function(){return this.data[2]};c.prototype.getPitchBend=function(){return this.data[1]+
-(this.data[2]<<7)-8192};c.computePitchBend=function(c,e){return c+(e<<7)-8192};c.prototype.setCommandFromString=function(e){this.cmd=c.computeCommandFromString(e)};c.computeCommandFromString=function(e){if(!e)return 0;if(e&&e.constructor===Number)return e;e=e.toUpperCase();switch(e){case "NOTE ON":case "NOTEON":return c.NOTEON;case "NOTE OFF":case "NOTEOFF":return c.NOTEON;case "KEY PRESSURE":case "KEYPRESSURE":return c.KEYPRESSURE;case "CONTROLLER CHANGE":case "CONTROLLERCHANGE":case "CC":return c.CONTROLLERCHANGE;
-case "PROGRAM CHANGE":case "PROGRAMCHANGE":case "PC":return c.PROGRAMCHANGE;case "CHANNEL PRESSURE":case "CHANNELPRESSURE":return c.CHANNELPRESSURE;case "PITCH BEND":case "PITCHBEND":return c.PITCHBEND;case "TIME TICK":case "TIMETICK":return c.TIMETICK;default:return Number(e)}};c.toNoteString=function(e,f){e=Math.round(e);var g,a=Math.floor((e-24)/12+1);g=(e-21)%12;0>g&&(g=12+g);return c.notes[g]+(f?"":a)};c.NoteStringToPitch=function(e){e=e.toUpperCase();var f=e[0],g=4;"#"==e[1]?(f+="#",2this.properties.max_value)return;this.trigger("on_midi",f)}};m.registerNodeType("midi/filter",g);y.title="MIDIEvent";y.desc="Create a MIDI Event";y.color="#243";y.prototype.onAction=function(e,f){"assign"==
-e?(this.properties.channel=f.channel,this.properties.cmd=f.cmd,this.properties.value1=f.data[1],this.properties.value2=f.data[2],f.cmd==c.NOTEON?this.gate=!0:f.cmd==c.NOTEOFF&&(this.gate=!1)):(f=this.midi_event,f.channel=this.properties.channel,this.properties.cmd&&this.properties.cmd.constructor===String?f.setCommandFromString(this.properties.cmd):f.cmd=this.properties.cmd,f.data[0]=f.cmd|f.channel,f.data[1]=Number(this.properties.value1),f.data[2]=Number(this.properties.value2),this.trigger("on_midi",
-f))};y.prototype.onExecute=function(){var e=this.properties;if(this.inputs)for(var f=0;fc;++c)this.valid_notes[c]=-1!=this.notes_pitches.indexOf(c);for(c=0;12>c;++c)if(this.valid_notes[c])this.offset_notes[c]=0;else for(var e=
-1;12>e;++e){if(this.valid_notes[(c-e)%12]){this.offset_notes[c]=-e;break}if(this.valid_notes[(c+e)%12]){this.offset_notes[c]=e;break}}};e.prototype.onAction=function(e,f){f&&f.constructor===c&&(f.data[0]==c.NOTEON||f.data[0]==c.NOTEOFF?(this.midi_event=new c,this.midi_event.setup(f.data),this.midi_event.data[1]+=this.offset_notes[c.note_to_index[f.note]],this.trigger("out",this.midi_event)):this.trigger("out",f))};e.prototype.onExecute=function(){var c=this.getInputData(1);null!=c&&c!=this._current_scale&&
-this.processScale(c)};m.registerNodeType("midi/quantize",e);v.title="MIDI Play";v.desc="Plays a MIDI note";v.color="#243";v.prototype.onAction=function(e,f){if(f&&f.constructor===c){if(this.instrument&&f.data[0]==c.NOTEON){var g=f.note;if(!g||"undefined"==g||g.constructor!==String)return;this.instrument.play(g,f.octave,this.properties.duration,this.properties.volume)}this.trigger("note",f)}};v.prototype.onExecute=function(){var c=this.getInputData(1);null!=c&&(this.properties.volume=c);c=this.getInputData(2);
-null!=c&&(this.properties.duration=c)};m.registerNodeType("midi/play",v);k.title="MIDI Keys";k.desc="Keyboard to play notes";k.color="#243";k.keys=[{x:0,w:1,h:1,t:0},{x:0.75,w:0.5,h:0.6,t:1},{x:1,w:1,h:1,t:0},{x:1.75,w:0.5,h:0.6,t:1},{x:2,w:1,h:1,t:0},{x:2.75,w:0.5,h:0.6,t:1},{x:3,w:1,h:1,t:0},{x:4,w:1,h:1,t:0},{x:4.75,w:0.5,h:0.6,t:1},{x:5,w:1,h:1,t:0},{x:5.75,w:0.5,h:0.6,t:1},{x:6,w:1,h:1,t:0}];k.prototype.onDrawForeground=function(c){if(!this.flags.collapsed){var e=12*this.properties.num_octaves;
-this.keys.length=e;var f=this.size[0]/(7*this.properties.num_octaves),a=this.size[1];c.globalAlpha=1;for(var b=0;2>b;b++)for(var d=0;dg+l||c[1]>d))return b}}return-1};k.prototype.onAction=function(e,f){if("reset"==e)for(var g=0;gf[1])){var g=this.getKeyIndex(f);this.keys[g]=!0;this._last_key=
-g;var g=12*(this.properties.start_octave-1)+29+g,a=new c;a.setup([c.NOTEON,g,100]);this.trigger("note",a);return!0}};k.prototype.onMouseMove=function(e,f){if(!(0>f[1]||-1==this._last_key)){this.setDirtyCanvas(!0);var g=this.getKeyIndex(f);if(this._last_key==g)return!0;this.keys[this._last_key]=!1;var a=12*(this.properties.start_octave-1)+29+this._last_key,b=new c;b.setup([c.NOTEOFF,a,100]);this.trigger("note",b);this.keys[g]=!0;a=12*(this.properties.start_octave-1)+29+g;b=new c;b.setup([c.NOTEON,
-a,100]);this.trigger("note",b);this._last_key=g;return!0}};k.prototype.onMouseUp=function(e,f){if(!(0>f[1])){var g=this.getKeyIndex(f);this.keys[g]=!1;this._last_key=-1;var g=12*(this.properties.start_octave-1)+29+g,a=new c;a.setup([c.NOTEOFF,g,100]);this.trigger("note",a);return!0}};m.registerNodeType("midi/keys",k)})(this);
-(function(w){function c(){this.properties={src:"",gain:0.5,loop:!0,autoplay:!0,playbackRate:1};this._loading_audio=!1;this._audiobuffer=null;this._audionodes=[];this._last_sourcenode=null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=n.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain;this.properties.src&&this.loadSound(this.properties.src)}function q(){this.properties={gain:0.5};this._audionodes=[];this._media_stream=
-null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=n.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain}function f(){this.properties={fftSize:2048,minDecibels:-100,maxDecibels:-10,smoothingTimeConstant:0.5};this.audionode=n.getAudioContext().createAnalyser();this.audionode.graphnode=this;this.audionode.fftSize=this.properties.fftSize;this.audionode.minDecibels=this.properties.minDecibels;this.audionode.maxDecibels=
-this.properties.maxDecibels;this.audionode.smoothingTimeConstant=this.properties.smoothingTimeConstant;this.addInput("in","audio");this.addOutput("freqs","array");this.addOutput("samples","array");this._time_bin=this._freq_bin=null}function p(){this.properties={gain:1};this.audionode=n.getAudioContext().createGain();this.addInput("in","audio");this.addInput("gain","number");this.addOutput("out","audio")}function r(){this.properties={impulse_src:"",normalize:!0};this.audionode=n.getAudioContext().createConvolver();
-this.addInput("in","audio");this.addOutput("out","audio")}function g(){this.properties={threshold:-50,knee:40,ratio:12,reduction:-20,attack:0,release:0.25};this.audionode=n.getAudioContext().createDynamicsCompressor();this.addInput("in","audio");this.addOutput("out","audio")}function y(){this.properties={};this.audionode=n.getAudioContext().createWaveShaper();this.addInput("in","audio");this.addInput("shape","waveshape");this.addOutput("out","audio")}function s(){this.properties={gain1:0.5,gain2:0.5};
-this.audionode=n.getAudioContext().createGain();this.audionode1=n.getAudioContext().createGain();this.audionode1.gain.value=this.properties.gain1;this.audionode2=n.getAudioContext().createGain();this.audionode2.gain.value=this.properties.gain2;this.audionode1.connect(this.audionode);this.audionode2.connect(this.audionode);this.addInput("in1","audio");this.addInput("in1 gain","number");this.addInput("in2","audio");this.addInput("in2 gain","number");this.addOutput("out","audio")}function u(){this.properties=
-{A:0.1,D:0.1,S:0.1,R:0.1};this.audionode=n.getAudioContext().createGain();this.audionode.gain.value=0;this.addInput("in","audio");this.addInput("gate","bool");this.addOutput("out","audio");this.gate=!1}function z(){this.properties={delayTime:0.5};this.audionode=n.getAudioContext().createDelay(10);this.audionode.delayTime.value=this.properties.delayTime;this.addInput("in","audio");this.addInput("time","number");this.addOutput("out","audio")}function e(){this.properties={frequency:350,detune:0,Q:1};
-this.addProperty("type","lowpass","enum",{values:"lowpass highpass bandpass lowshelf highshelf peaking notch allpass".split(" ")});this.audionode=n.getAudioContext().createBiquadFilter();this.addInput("in","audio");this.addOutput("out","audio")}function v(){this.properties={frequency:440,detune:0,type:"sine"};this.addProperty("type","sine","enum",{values:["sine","square","sawtooth","triangle","custom"]});this.audionode=n.getAudioContext().createOscillator();this.addOutput("out","audio")}function k(){this.properties=
-{continuous:!0,mark:-1};this.addInput("data","array");this.addInput("mark","number");this.size=[300,200];this._last_buffer=null}function m(){this.properties={band:440,amplitude:1};this.addInput("freqs","array");this.addOutput("signal","number")}function C(){if(!C.default_code){var a=C.default_function.toString(),b=a.indexOf("{")+1,c=a.lastIndexOf("}");C.default_code=a.substr(b,c-b)}this.properties={code:C.default_code};a=n.getAudioContext();a.createScriptProcessor?this.audionode=a.createScriptProcessor(4096,
-1,1):(console.warn("ScriptProcessorNode deprecated"),this.audionode=a.createGain());this.processCode();C._bypass_function||(C._bypass_function=this.audionode.onaudioprocess);this.addInput("in","audio");this.addOutput("out","audio")}function h(){this.audionode=n.getAudioContext().destination;this.addInput("in","audio")}var t=w.LiteGraph,n={};w.LGAudio=n;n.getAudioContext=function(){if(!this._audio_context){window.AudioContext=window.AudioContext||window.webkitAudioContext;if(!window.AudioContext)return console.error("AudioContext not supported by browser"),
-null;this._audio_context=new AudioContext;this._audio_context.onmessage=function(a){console.log("msg",a)};this._audio_context.onended=function(a){console.log("ended",a)};this._audio_context.oncomplete=function(a){console.log("complete",a)}}return this._audio_context};n.connect=function(a,b){try{a.connect(b)}catch(c){console.warn("LGraphAudio:",c)}};n.disconnect=function(a,b){try{a.disconnect(b)}catch(c){console.warn("LGraphAudio:",c)}};n.changeAllAudiosConnections=function(a,b){if(a.inputs)for(var c=
-0;c=this.size[0]&&(f=this.size[0]-1),a.strokeStyle="red",a.beginPath(),a.moveTo(f,e),a.lineTo(f,0),a.stroke())}};k.title="Visualization";k.desc="Audio Visualization";t.registerNodeType("audio/visualization",k);m.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var a=this.properties.band,b=this.getInputData(1);void 0!==b&&(a=b);b=n.getAudioContext().sampleRate/this._freqs.length;b=a/b*2;b>=this._freqs.length?b=this._freqs[this._freqs.length-1]:(a=b|0,
-b-=a,b=this._freqs[a]*(1-b)+this._freqs[a+1]*b);this.setOutputData(0,b/255*this.properties.amplitude)}};m.prototype.onGetInputs=function(){return[["band","number"]]};m.title="Signal";m.desc="extract the signal of some frequency";t.registerNodeType("audio/signal",m);C.prototype.onAdded=function(a){a.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback)};C["@code"]={widget:"code"};C.prototype.onStart=function(){this.audionode.onaudioprocess=this._callback};C.prototype.onStop=
-function(){this.audionode.onaudioprocess=C._bypass_function};C.prototype.onPause=function(){this.audionode.onaudioprocess=C._bypass_function};C.prototype.onUnpause=function(){this.audionode.onaudioprocess=this._callback};C.prototype.onExecute=function(){};C.prototype.onRemoved=function(){this.audionode.onaudioprocess=C._bypass_function};C.prototype.processCode=function(){try{this._script=new new Function("properties",this.properties.code)(this.properties),this._old_code=this.properties.code,this._callback=
-this._script.onaudioprocess}catch(a){console.error("Error in onaudioprocess code",a),this._callback=C._bypass_function,this.audionode.onaudioprocess=this._callback}};C.prototype.onPropertyChanged=function(a,b){"code"==a&&(this.properties.code=b,this.processCode(),this.graph&&this.graph.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback))};C.default_function=function(){this.onaudioprocess=function(a){var b=a.inputBuffer;a=a.outputBuffer;for(var c=0;c=b.NOTEON||h<=b.NOTEOFF)this.channel=
+e&15};Object.defineProperty(b.prototype,"velocity",{get:function(){return this.cmd==b.NOTEON?this.data[2]:-1},set:function(b){this.data[2]=b},enumerable:!0});b.notes="A A# B C C# D D# E F F# G G#".split(" ");b.note_to_index={A:0,"A#":1,B:2,C:3,"C#":4,D:5,"D#":6,E:7,F:8,"F#":9,G:10,"G#":11};Object.defineProperty(b.prototype,"note",{get:function(){return this.cmd!=b.NOTEON?-1:b.toNoteString(this.data[1],!0)},set:function(b){throw"notes cannot be assigned this way, must modify the data[1]";},enumerable:!0});
+Object.defineProperty(b.prototype,"octave",{get:function(){return this.cmd!=b.NOTEON?-1:Math.floor((this.data[1]-24)/12+1)},set:function(b){throw"octave cannot be assigned this way, must modify the data[1]";},enumerable:!0});b.prototype.getPitch=function(){return 440*Math.pow(2,(this.data[1]-69)/12)};b.computePitch=function(b){return 440*Math.pow(2,(b-69)/12)};b.prototype.getCC=function(){return this.data[1]};b.prototype.getCCValue=function(){return this.data[2]};b.prototype.getPitchBend=function(){return this.data[1]+
+(this.data[2]<<7)-8192};b.computePitchBend=function(b,e){return b+(e<<7)-8192};b.prototype.setCommandFromString=function(e){this.cmd=b.computeCommandFromString(e)};b.computeCommandFromString=function(e){if(!e)return 0;if(e&&e.constructor===Number)return e;e=e.toUpperCase();switch(e){case "NOTE ON":case "NOTEON":return b.NOTEON;case "NOTE OFF":case "NOTEOFF":return b.NOTEON;case "KEY PRESSURE":case "KEYPRESSURE":return b.KEYPRESSURE;case "CONTROLLER CHANGE":case "CONTROLLERCHANGE":case "CC":return b.CONTROLLERCHANGE;
+case "PROGRAM CHANGE":case "PROGRAMCHANGE":case "PC":return b.PROGRAMCHANGE;case "CHANNEL PRESSURE":case "CHANNELPRESSURE":return b.CHANNELPRESSURE;case "PITCH BEND":case "PITCHBEND":return b.PITCHBEND;case "TIME TICK":case "TIMETICK":return b.TIMETICK;default:return Number(e)}};b.toNoteString=function(e,h){e=Math.round(e);var l,k=Math.floor((e-24)/12+1);l=(e-21)%12;0>l&&(l=12+l);return b.notes[l]+(h?"":k)};b.NoteStringToPitch=function(e){e=e.toUpperCase();var h=e[0],l=4;"#"==e[1]?(h+="#",2this.properties.max_value)return;this.trigger("on_midi",h)}};r.registerNodeType("midi/filter",h);D.title="MIDIEvent";D.desc="Create a MIDI Event";D.color="#243";D.prototype.onAction=function(e,h){"assign"==
+e?(this.properties.channel=h.channel,this.properties.cmd=h.cmd,this.properties.value1=h.data[1],this.properties.value2=h.data[2],h.cmd==b.NOTEON?this.gate=!0:h.cmd==b.NOTEOFF&&(this.gate=!1)):(h=this.midi_event,h.channel=this.properties.channel,this.properties.cmd&&this.properties.cmd.constructor===String?h.setCommandFromString(this.properties.cmd):h.cmd=this.properties.cmd,h.data[0]=h.cmd|h.channel,h.data[1]=Number(this.properties.value1),h.data[2]=Number(this.properties.value2),this.trigger("on_midi",
+h))};D.prototype.onExecute=function(){var e=this.properties;if(this.inputs)for(var h=0;hb;++b)this.valid_notes[b]=-1!=this.notes_pitches.indexOf(b);for(b=0;12>b;++b)if(this.valid_notes[b])this.offset_notes[b]=0;else for(var e=
+1;12>e;++e){if(this.valid_notes[(b-e)%12]){this.offset_notes[b]=-e;break}if(this.valid_notes[(b+e)%12]){this.offset_notes[b]=e;break}}};l.prototype.onAction=function(e,h){h&&h.constructor===b&&(h.data[0]==b.NOTEON||h.data[0]==b.NOTEOFF?(this.midi_event=new b,this.midi_event.setup(h.data),this.midi_event.data[1]+=this.offset_notes[b.note_to_index[h.note]],this.trigger("out",this.midi_event)):this.trigger("out",h))};l.prototype.onExecute=function(){var b=this.getInputData(1);null!=b&&b!=this._current_scale&&
+this.processScale(b)};r.registerNodeType("midi/quantize",l);e.title="MIDI Play";e.desc="Plays a MIDI note";e.color="#243";e.prototype.onAction=function(e,h){if(h&&h.constructor===b){if(this.instrument&&h.data[0]==b.NOTEON){var l=h.note;if(!l||"undefined"==l||l.constructor!==String)return;this.instrument.play(l,h.octave,this.properties.duration,this.properties.volume)}this.trigger("note",h)}};e.prototype.onExecute=function(){var b=this.getInputData(1);null!=b&&(this.properties.volume=b);b=this.getInputData(2);
+null!=b&&(this.properties.duration=b)};r.registerNodeType("midi/play",e);C.title="MIDI Keys";C.desc="Keyboard to play notes";C.color="#243";C.keys=[{x:0,w:1,h:1,t:0},{x:0.75,w:0.5,h:0.6,t:1},{x:1,w:1,h:1,t:0},{x:1.75,w:0.5,h:0.6,t:1},{x:2,w:1,h:1,t:0},{x:2.75,w:0.5,h:0.6,t:1},{x:3,w:1,h:1,t:0},{x:4,w:1,h:1,t:0},{x:4.75,w:0.5,h:0.6,t:1},{x:5,w:1,h:1,t:0},{x:5.75,w:0.5,h:0.6,t:1},{x:6,w:1,h:1,t:0}];C.prototype.onDrawForeground=function(b){if(!this.flags.collapsed){var e=12*this.properties.num_octaves;
+this.keys.length=e;var h=this.size[0]/(7*this.properties.num_octaves),k=this.size[1];b.globalAlpha=1;for(var a=0;2>a;a++)for(var c=0;cd+g||b[1]>c))return a}}return-1};C.prototype.onAction=function(e,h){if("reset"==e)for(var l=0;lh[1])){var l=this.getKeyIndex(h);this.keys[l]=!0;this._last_key=
+l;var l=12*(this.properties.start_octave-1)+29+l,k=new b;k.setup([b.NOTEON,l,100]);this.trigger("note",k);return!0}};C.prototype.onMouseMove=function(e,h){if(!(0>h[1]||-1==this._last_key)){this.setDirtyCanvas(!0);var l=this.getKeyIndex(h);if(this._last_key==l)return!0;this.keys[this._last_key]=!1;var k=12*(this.properties.start_octave-1)+29+this._last_key,a=new b;a.setup([b.NOTEOFF,k,100]);this.trigger("note",a);this.keys[l]=!0;k=12*(this.properties.start_octave-1)+29+l;a=new b;a.setup([b.NOTEON,
+k,100]);this.trigger("note",a);this._last_key=l;return!0}};C.prototype.onMouseUp=function(e,h){if(!(0>h[1])){var l=this.getKeyIndex(h);this.keys[l]=!1;this._last_key=-1;var l=12*(this.properties.start_octave-1)+29+l,k=new b;k.setup([b.NOTEOFF,l,100]);this.trigger("note",k);return!0}};r.registerNodeType("midi/keys",C)})(this);
+(function(z){function b(){this.properties={src:"",gain:0.5,loop:!0,autoplay:!0,playbackRate:1};this._loading_audio=!1;this._audiobuffer=null;this._audionodes=[];this._last_sourcenode=null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=t.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain;this.properties.src&&this.loadSound(this.properties.src)}function m(){this.properties={gain:0.5};this._audionodes=[];this._media_stream=
+null;this.addOutput("out","audio");this.addInput("gain","number");this.audionode=t.getAudioContext().createGain();this.audionode.graphnode=this;this.audionode.gain.value=this.properties.gain}function q(){this.properties={fftSize:2048,minDecibels:-100,maxDecibels:-10,smoothingTimeConstant:0.5};this.audionode=t.getAudioContext().createAnalyser();this.audionode.graphnode=this;this.audionode.fftSize=this.properties.fftSize;this.audionode.minDecibels=this.properties.minDecibels;this.audionode.maxDecibels=
+this.properties.maxDecibels;this.audionode.smoothingTimeConstant=this.properties.smoothingTimeConstant;this.addInput("in","audio");this.addOutput("freqs","array");this.addOutput("samples","array");this._time_bin=this._freq_bin=null}function p(){this.properties={gain:1};this.audionode=t.getAudioContext().createGain();this.addInput("in","audio");this.addInput("gain","number");this.addOutput("out","audio")}function y(){this.properties={impulse_src:"",normalize:!0};this.audionode=t.getAudioContext().createConvolver();
+this.addInput("in","audio");this.addOutput("out","audio")}function h(){this.properties={threshold:-50,knee:40,ratio:12,reduction:-20,attack:0,release:0.25};this.audionode=t.getAudioContext().createDynamicsCompressor();this.addInput("in","audio");this.addOutput("out","audio")}function D(){this.properties={};this.audionode=t.getAudioContext().createWaveShaper();this.addInput("in","audio");this.addInput("shape","waveshape");this.addOutput("out","audio")}function v(){this.properties={gain1:0.5,gain2:0.5};
+this.audionode=t.getAudioContext().createGain();this.audionode1=t.getAudioContext().createGain();this.audionode1.gain.value=this.properties.gain1;this.audionode2=t.getAudioContext().createGain();this.audionode2.gain.value=this.properties.gain2;this.audionode1.connect(this.audionode);this.audionode2.connect(this.audionode);this.addInput("in1","audio");this.addInput("in1 gain","number");this.addInput("in2","audio");this.addInput("in2 gain","number");this.addOutput("out","audio")}function w(){this.properties=
+{A:0.1,D:0.1,S:0.1,R:0.1};this.audionode=t.getAudioContext().createGain();this.audionode.gain.value=0;this.addInput("in","audio");this.addInput("gate","bool");this.addOutput("out","audio");this.gate=!1}function B(){this.properties={delayTime:0.5};this.audionode=t.getAudioContext().createDelay(10);this.audionode.delayTime.value=this.properties.delayTime;this.addInput("in","audio");this.addInput("time","number");this.addOutput("out","audio")}function l(){this.properties={frequency:350,detune:0,Q:1};
+this.addProperty("type","lowpass","enum",{values:"lowpass highpass bandpass lowshelf highshelf peaking notch allpass".split(" ")});this.audionode=t.getAudioContext().createBiquadFilter();this.addInput("in","audio");this.addOutput("out","audio")}function e(){this.properties={frequency:440,detune:0,type:"sine"};this.addProperty("type","sine","enum",{values:["sine","square","sawtooth","triangle","custom"]});this.audionode=t.getAudioContext().createOscillator();this.addOutput("out","audio")}function C(){this.properties=
+{continuous:!0,mark:-1};this.addInput("data","array");this.addInput("mark","number");this.size=[300,200];this._last_buffer=null}function r(){this.properties={band:440,amplitude:1};this.addInput("freqs","array");this.addOutput("signal","number")}function A(){if(!A.default_code){var b=A.default_function.toString(),a=b.indexOf("{")+1,c=b.lastIndexOf("}");A.default_code=b.substr(a,c-a)}this.properties={code:A.default_code};b=t.getAudioContext();b.createScriptProcessor?this.audionode=b.createScriptProcessor(4096,
+1,1):(console.warn("ScriptProcessorNode deprecated"),this.audionode=b.createGain());this.processCode();A._bypass_function||(A._bypass_function=this.audionode.onaudioprocess);this.addInput("in","audio");this.addOutput("out","audio")}function s(){this.audionode=t.getAudioContext().destination;this.addInput("in","audio")}var n=z.LiteGraph,t={};z.LGAudio=t;t.getAudioContext=function(){if(!this._audio_context){window.AudioContext=window.AudioContext||window.webkitAudioContext;if(!window.AudioContext)return console.error("AudioContext not supported by browser"),
+null;this._audio_context=new AudioContext;this._audio_context.onmessage=function(b){console.log("msg",b)};this._audio_context.onended=function(b){console.log("ended",b)};this._audio_context.oncomplete=function(b){console.log("complete",b)}}return this._audio_context};t.connect=function(b,a){try{b.connect(a)}catch(c){console.warn("LGraphAudio:",c)}};t.disconnect=function(b,a){try{b.disconnect(a)}catch(c){console.warn("LGraphAudio:",c)}};t.changeAllAudiosConnections=function(b,a){if(b.inputs)for(var c=
+0;c=this.size[0]&&(e=this.size[0]-1),b.strokeStyle="red",b.beginPath(),b.moveTo(e,d),b.lineTo(e,0),b.stroke())}};C.title="Visualization";C.desc="Audio Visualization";n.registerNodeType("audio/visualization",C);r.prototype.onExecute=function(){if(this._freqs=this.getInputData(0)){var b=this.properties.band,a=this.getInputData(1);void 0!==a&&(b=a);a=t.getAudioContext().sampleRate/this._freqs.length;a=b/a*2;a>=this._freqs.length?a=this._freqs[this._freqs.length-1]:(b=a|0,
+a-=b,a=this._freqs[b]*(1-a)+this._freqs[b+1]*a);this.setOutputData(0,a/255*this.properties.amplitude)}};r.prototype.onGetInputs=function(){return[["band","number"]]};r.title="Signal";r.desc="extract the signal of some frequency";n.registerNodeType("audio/signal",r);A.prototype.onAdded=function(b){b.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback)};A["@code"]={widget:"code"};A.prototype.onStart=function(){this.audionode.onaudioprocess=this._callback};A.prototype.onStop=
+function(){this.audionode.onaudioprocess=A._bypass_function};A.prototype.onPause=function(){this.audionode.onaudioprocess=A._bypass_function};A.prototype.onUnpause=function(){this.audionode.onaudioprocess=this._callback};A.prototype.onExecute=function(){};A.prototype.onRemoved=function(){this.audionode.onaudioprocess=A._bypass_function};A.prototype.processCode=function(){try{this._script=new new Function("properties",this.properties.code)(this.properties),this._old_code=this.properties.code,this._callback=
+this._script.onaudioprocess}catch(b){console.error("Error in onaudioprocess code",b),this._callback=A._bypass_function,this.audionode.onaudioprocess=this._callback}};A.prototype.onPropertyChanged=function(b,a){"code"==b&&(this.properties.code=a,this.processCode(),this.graph&&this.graph.status==LGraph.STATUS_RUNNING&&(this.audionode.onaudioprocess=this._callback))};A.default_function=function(){this.onaudioprocess=function(b){var a=b.inputBuffer;b=b.outputBuffer;for(var c=0;c max_size) {
max_size = node.size[0];
}
- y += node.size[1] + margin;
+ y += node.size[1] + margin + LiteGraph.NODE_TITLE_HEIGHT;
}
x += max_size + margin;
}
@@ -1893,6 +1893,8 @@
//copy all stored fields
for (var i in data) {
+ if(i == "nodes" || i == "groups")
+ continue;
this[i] = data[i];
}
@@ -2033,7 +2035,7 @@
+ skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected
+ resizable: if set to false it wont be resizable with the mouse
+ horizontal: slots are distributed horizontally
- + widgets_up: widgets start from the top of the node
+ + widgets_start_y: widgets start at y distance from the top of the node
flags object:
+ collapsed: if it is collapsed
@@ -2398,7 +2400,9 @@
if (this.outputs[slot].links) {
for (var i = 0; i < this.outputs[slot].links.length; i++) {
var link_id = this.outputs[slot].links[i];
- this.graph.links[link_id].data = data;
+ var link = this.graph.links[link_id];
+ if(link)
+ link.data = data;
}
}
};
@@ -2712,19 +2716,13 @@
return;
}
- if (this.graph) {
+ if (this.graph)
this.graph._last_trigger_time = LiteGraph.getTime();
- }
for (var i = 0; i < this.outputs.length; ++i) {
var output = this.outputs[i];
- if (
- !output ||
- output.type !== LiteGraph.EVENT ||
- (action && output.name != action)
- ) {
+ if ( !output || output.type !== LiteGraph.EVENT || (action && output.name != action) )
continue;
- }
this.triggerSlot(i, param);
}
};
@@ -3060,19 +3058,20 @@
var size = out || new Float32Array([0, 0]);
rows = Math.max(rows, 1);
var font_size = LiteGraph.NODE_TEXT_SIZE; //although it should be graphcanvas.inner_text_font size
- size[1] =
- (this.constructor.slot_start_y || 0) +
- rows * LiteGraph.NODE_SLOT_HEIGHT;
+ size[1] = (this.constructor.slot_start_y || 0) + rows * LiteGraph.NODE_SLOT_HEIGHT;
+
var widgets_height = 0;
if (this.widgets && this.widgets.length) {
- widgets_height =
- this.widgets.length * (LiteGraph.NODE_WIDGET_HEIGHT + 4) + 8;
+ widgets_height = this.widgets.length * (LiteGraph.NODE_WIDGET_HEIGHT + 4) + 8;
}
- if (this.widgets_up) {
- size[1] = Math.max(size[1], widgets_height);
- } else {
+
+ //compute height using widgets height
+ if( this.widgets_up )
+ size[1] = Math.max( size[1], widgets_height );
+ else if( this.widgets_start_y != null )
+ size[1] = Math.max( size[1], widgets_height + this.widgets_start_y );
+ else
size[1] += widgets_height;
- }
var font_size = font_size;
var title_width = compute_text_size(this.title);
@@ -5097,10 +5096,7 @@ LGraphNode.prototype.executeAction = function(action)
}
//if do not capture mouse
- if (
- node.onMouseDown &&
- node.onMouseDown( e, [e.canvasX - node.pos[0], e.canvasY - node.pos[1]], this )
- ) {
+ if ( node.onMouseDown && node.onMouseDown( e, [e.canvasX - node.pos[0], e.canvasY - node.pos[1]], this ) ) {
block_drag_node = true;
} else if (this.live_mode) {
clicking_canvas_bg = true;
@@ -5136,6 +5132,7 @@ LGraphNode.prototype.executeAction = function(action)
}
//link clicked
this.showLinkMenu(link, e);
+ this.over_link_center = null; //clear tooltip
break;
}
@@ -5396,12 +5393,8 @@ LGraphNode.prototype.executeAction = function(action)
}
}
- if (
- this.node_capturing_input &&
- this.node_capturing_input != node &&
- this.node_capturing_input.onMouseMove
- ) {
- this.node_capturing_input.onMouseMove(e);
+ if ( this.node_capturing_input && this.node_capturing_input != node && this.node_capturing_input.onMouseMove ) {
+ this.node_capturing_input.onMouseMove(e,[e.canvasX - this.node_capturing_input.pos[0],e.canvasY - this.node_capturing_input.pos[1]], this);
}
if (this.node_dragged && !this.live_mode) {
@@ -5417,27 +5410,17 @@ LGraphNode.prototype.executeAction = function(action)
if (this.resizing_node && !this.live_mode) {
//convert mouse to node space
- this.resizing_node.size[0] =
- e.canvasX - this.resizing_node.pos[0];
- this.resizing_node.size[1] =
- e.canvasY - this.resizing_node.pos[1];
+ this.resizing_node.size[0] = e.canvasX - this.resizing_node.pos[0];
+ this.resizing_node.size[1] = e.canvasY - this.resizing_node.pos[1];
//constraint size
var max_slots = Math.max(
- this.resizing_node.inputs
- ? this.resizing_node.inputs.length
- : 0,
- this.resizing_node.outputs
- ? this.resizing_node.outputs.length
- : 0
+ this.resizing_node.inputs ? this.resizing_node.inputs.length : 0,
+ this.resizing_node.outputs ? this.resizing_node.outputs.length : 0
);
var min_height =
max_slots * LiteGraph.NODE_SLOT_HEIGHT +
- (this.resizing_node.widgets
- ? this.resizing_node.widgets.length
- : 0) *
- (LiteGraph.NODE_WIDGET_HEIGHT + 4) +
- 4;
+ (this.resizing_node.widgets ? this.resizing_node.widgets.length : 0) * (LiteGraph.NODE_WIDGET_HEIGHT + 4) + 4;
if (this.resizing_node.size[1] < min_height) {
this.resizing_node.size[1] = min_height;
}
@@ -5663,14 +5646,7 @@ LGraphNode.prototype.executeAction = function(action)
this.dragging_canvas = false;
if (this.node_over && this.node_over.onMouseUp) {
- this.node_over.onMouseUp(
- e,
- [
- e.canvasX - this.node_over.pos[0],
- e.canvasY - this.node_over.pos[1]
- ],
- this
- );
+ this.node_over.onMouseUp( e, [ e.canvasX - this.node_over.pos[0], e.canvasY - this.node_over.pos[1] ], this );
}
if (
this.node_capturing_input &&
@@ -5971,7 +5947,10 @@ LGraphNode.prototype.executeAction = function(action)
var link_info = clipboard_info.links[i];
var origin_node = nodes[link_info[0]];
var target_node = nodes[link_info[2]];
- origin_node.connect(link_info[1], target_node, link_info[3]);
+ if( origin_node && target_node )
+ origin_node.connect(link_info[1], target_node, link_info[3]);
+ else
+ console.warn("Warning, nodes missing on pasting");
}
this.selectNodes(nodes);
@@ -6219,7 +6198,16 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.prototype.deleteSelectedNodes = function() {
for (var i in this.selected_nodes) {
var node = this.selected_nodes[i];
- //if(m == this.node_in_panel) this.showNodePanel(null);
+ //autoconnect when possible (very basic, only takes into account first input-output)
+ if(node.inputs && node.inputs.length && node.outputs && node.outputs.length && LiteGraph.isValidConnection( node.inputs[0].type, node.outputs[0].type ) && node.inputs[0].link && node.outputs[0].links && node.outputs[0].links.length )
+ {
+ var input_link = node.graph.links[ node.inputs[0].link ];
+ var output_link = node.graph.links[ node.outputs[0].links[0] ];
+ var input_node = node.getInputNode(0);
+ var output_node = node.getOutputNodes(0)[0];
+ if(input_node && output_node)
+ input_node.connect( input_link.origin_slot, output_node, output_link.target_slot );
+ }
this.graph.remove(node);
if (this.onNodeDeselected) {
this.onNodeDeselected(node);
@@ -7114,12 +7102,15 @@ LGraphNode.prototype.executeAction = function(action)
ctx.globalAlpha = 1;
if (node.widgets) {
+ var widgets_y = max_y;
if (horizontal || node.widgets_up) {
- max_y = 2;
+ widgets_y = 2;
}
+ if( node.widgets_start_y != null )
+ widgets_y = node.widgets_start_y;
this.drawNodeWidgets(
node,
- max_y,
+ widgets_y,
ctx,
this.node_widget && this.node_widget[0] == node
? this.node_widget[1]
@@ -8109,6 +8100,8 @@ LGraphNode.prototype.executeAction = function(action)
ctx.strokeStyle = outline_color;
ctx.fillStyle = "#222";
ctx.textAlign = "left";
+ if(w.disabled)
+ ctx.globalAlpha *= 0.5;
switch (w.type) {
case "button":
@@ -8258,6 +8251,8 @@ LGraphNode.prototype.executeAction = function(action)
break;
}
posY += H + 4;
+ ctx.globalAlpha = this.editor_alpha;
+
}
ctx.restore();
ctx.textAlign = "left";
@@ -8285,13 +8280,9 @@ LGraphNode.prototype.executeAction = function(action)
for (var i = 0; i < node.widgets.length; ++i) {
var w = node.widgets[i];
- if (
- w == active_widget ||
- (x > 6 &&
- x < width - 12 &&
- y > w.last_y &&
- y < w.last_y + LiteGraph.NODE_WIDGET_HEIGHT)
- ) {
+ if(w.disabled)
+ continue;
+ if ( w == active_widget || (x > 6 && x < width - 12 && y > w.last_y && y < w.last_y + LiteGraph.NODE_WIDGET_HEIGHT) ) {
//inside widget
switch (w.type) {
case "button":
@@ -8300,7 +8291,7 @@ LGraphNode.prototype.executeAction = function(action)
}
if (w.callback) {
setTimeout(function() {
- w.callback(w, that, node, pos);
+ w.callback(w, that, node, pos, event);
}, 20);
}
w.clicked = true;
@@ -8396,11 +8387,9 @@ LGraphNode.prototype.executeAction = function(action)
case "toggle":
if (event.type == "mousedown") {
w.value = !w.value;
- if (w.callback) {
- setTimeout(function() {
- inner_value_change(w, w.value);
- }, 20);
- }
+ setTimeout(function() {
+ inner_value_change(w, w.value);
+ }, 20);
}
break;
case "string":
@@ -8620,7 +8609,7 @@ LGraphNode.prototype.executeAction = function(action)
canvas.graph.add(group);
};
- LGraphCanvas.onMenuAdd = function(node, options, e, prev_menu) {
+ LGraphCanvas.onMenuAdd = function(node, options, e, prev_menu, callback) {
var canvas = LGraphCanvas.active_canvas;
var ref_window = canvas.getCanvasWindow();
@@ -8659,6 +8648,8 @@ LGraphNode.prototype.executeAction = function(action)
node.pos = canvas.convertEventToCanvasOffset(first_event);
canvas.graph.add(node);
}
+ if(callback)
+ callback(node);
}
return false;
@@ -8931,15 +8922,31 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.prototype.showLinkMenu = function(link, e) {
var that = this;
- console.log(link.data);
- new LiteGraph.ContextMenu(["Delete"], {
+ console.log(link);
+ var options = ["Add Node",null,"Delete"];
+ var menu = new LiteGraph.ContextMenu(options, {
event: e,
title: link.data != null ? link.data.constructor.name : null,
callback: inner_clicked
});
- function inner_clicked(v) {
+ function inner_clicked(v,options,e) {
switch (v) {
+ case "Add Node":
+ LGraphCanvas.onMenuAdd(null, null, e, menu, function(node){
+ console.log("node autoconnect");
+ var node_left = that.graph.getNodeById( link.origin_id );
+ var node_right = that.graph.getNodeById( link.target_id );
+ if(!node.inputs || !node.inputs.length || !node.outputs || !node.outputs.length)
+ return;
+ if( node_left.outputs[ link.origin_slot ].type == node.inputs[0].type && node.outputs[0].type == node_right.inputs[0].type )
+ {
+ node_left.connect( link.origin_slot, node, 0 );
+ node.connect( 0, node_right, link.target_slot );
+ node.pos[0] -= node.size[0] * 0.5;
+ }
+ });
+ break;
case "Delete":
that.graph.removeLink(link.id);
break;
@@ -9118,6 +9125,9 @@ LGraphNode.prototype.executeAction = function(action)
LGraphCanvas.prototype.showSearchBox = function(event) {
var that = this;
var input_html = "";
+ var graphcanvas = LGraphCanvas.active_canvas;
+ var canvas = graphcanvas.canvas;
+ var root_document = canvas.ownerDocument || document;
var dialog = document.createElement("div");
dialog.className = "litegraph litesearchbox graphdialog rounded";
@@ -9125,7 +9135,9 @@ LGraphNode.prototype.executeAction = function(action)
"Search ";
dialog.close = function() {
that.search_box = null;
- document.body.focus();
+ root_document.body.focus();
+ root_document.body.style.overflow = "";
+
setTimeout(function() {
that.canvas.focus();
}, 20); //important, if canvas loses focus keys wont be captured
@@ -9202,14 +9214,13 @@ LGraphNode.prototype.executeAction = function(action)
});
}
- var graphcanvas = LGraphCanvas.active_canvas;
- var canvas = graphcanvas.canvas;
-
- var root_document = canvas.ownerDocument || document;
if( root_document.fullscreenElement )
root_document.fullscreenElement.appendChild(dialog);
else
+ {
root_document.body.appendChild(dialog);
+ root_document.body.style.overflow = "hidden";
+ }
//compute best position
var rect = canvas.getBoundingClientRect();
@@ -9219,6 +9230,10 @@ LGraphNode.prototype.executeAction = function(action)
dialog.style.left = left + "px";
dialog.style.top = top + "px";
+ //To avoid out of screen problems
+ if(event.layerY > (rect.height - 200))
+ helper.style.maxHeight = (rect.height - event.layerY - 20) + "px";
+
/*
var offsetx = -20;
var offsety = -20;
@@ -9315,7 +9330,7 @@ LGraphNode.prototype.executeAction = function(action)
return;
}
selected.classList.add("selected");
- selected.scrollIntoView({block: "end", behaviour: "smooth"});
+ selected.scrollIntoView({block: "end", behavior: "smooth"});
}
function refreshHelper() {
@@ -10650,6 +10665,184 @@ LGraphNode.prototype.executeAction = function(action)
}
};
+ //used by some widgets to render a curve editor
+ function CurveEditor( points )
+ {
+ this.points = points;
+ this.selected = -1;
+ this.nearest = -1;
+ this.size = null; //stores last size used
+ this.must_update = true;
+ this.margin = 5;
+ }
+
+ CurveEditor.sampleCurve = function(f,points)
+ {
+ if(!points)
+ return;
+ for(var i = 0; i < points.length - 1; ++i)
+ {
+ var p = points[i];
+ var pn = points[i+1];
+ if(pn[0] < f)
+ continue;
+ var r = (pn[0] - p[0]);
+ if( Math.abs(r) < 0.00001 )
+ return p[1];
+ var local_f = (f - p[0]) / r;
+ return p[1] * (1.0 - local_f) + pn[1] * local_f;
+ }
+ return 0;
+ }
+
+ CurveEditor.prototype.draw = function( ctx, size, graphcanvas, background_color, line_color, inactive )
+ {
+ var points = this.points;
+ if(!points)
+ return;
+ this.size = size;
+ var w = size[0] - this.margin * 2;
+ var h = size[1] - this.margin * 2;
+
+ line_color = line_color || "#666";
+
+ ctx.save();
+ ctx.translate(this.margin,this.margin);
+
+ if(background_color)
+ {
+ ctx.fillStyle = "#111";
+ ctx.fillRect(0,0,w,h);
+ ctx.fillStyle = "#222";
+ ctx.fillRect(w*0.5,0,1,h);
+ ctx.strokeStyle = "#333";
+ ctx.strokeRect(0,0,w,h);
+ }
+ ctx.strokeStyle = line_color;
+ if(inactive)
+ ctx.globalAlpha = 0.5;
+ ctx.beginPath();
+ for(var i = 0; i < points.length; ++i)
+ {
+ var p = points[i];
+ ctx.lineTo( p[0] * w, (1.0 - p[1]) * h );
+ }
+ ctx.stroke();
+ ctx.globalAlpha = 1;
+ if(!inactive)
+ for(var i = 0; i < points.length; ++i)
+ {
+ var p = points[i];
+ ctx.fillStyle = this.selected == i ? "#FFF" : (this.nearest == i ? "#DDD" : "#AAA");
+ ctx.beginPath();
+ ctx.arc( p[0] * w, (1.0 - p[1]) * h, 2, 0, Math.PI * 2 );
+ ctx.fill();
+ }
+ ctx.restore();
+ }
+
+ //localpos is mouse in curve editor space
+ CurveEditor.prototype.onMouseDown = function( localpos, graphcanvas )
+ {
+ var points = this.points;
+ if(!points)
+ return;
+ if( localpos[1] < 0 )
+ return;
+
+ //this.captureInput(true);
+ var w = this.size[0] - this.margin * 2;
+ var h = this.size[1] - this.margin * 2;
+ var x = localpos[0] - this.margin;
+ var y = localpos[1] - this.margin;
+ var pos = [x,y];
+ var max_dist = 30 / graphcanvas.ds.scale;
+ //search closer one
+ this.selected = this.getCloserPoint(pos, max_dist);
+ //create one
+ if(this.selected == -1)
+ {
+ var point = [x / w, 1 - y / h];
+ points.push(point);
+ points.sort(function(a,b){ return a[0] - b[0]; });
+ this.selected = points.indexOf(point);
+ this.must_update = true;
+ }
+ if(this.selected != -1)
+ return true;
+ }
+
+ CurveEditor.prototype.onMouseMove = function( localpos, graphcanvas )
+ {
+ var points = this.points;
+ if(!points)
+ return;
+ var s = this.selected;
+ if(s < 0)
+ return;
+ var x = (localpos[0] - this.margin) / (this.size[0] - this.margin * 2 );
+ var y = (localpos[1] - this.margin) / (this.size[1] - this.margin * 2 );
+ var curvepos = [(localpos[0] - this.margin),(localpos[1] - this.margin)];
+ var max_dist = 30 / graphcanvas.ds.scale;
+ this._nearest = this.getCloserPoint(curvepos, max_dist);
+ var point = points[s];
+ if(point)
+ {
+ var is_edge_point = s == 0 || s == points.length - 1;
+ if( !is_edge_point && (localpos[0] < -10 || localpos[0] > this.size[0] + 10 || localpos[1] < -10 || localpos[1] > this.size[1] + 10) )
+ {
+ points.splice(s,1);
+ this.selected = -1;
+ return;
+ }
+ if( !is_edge_point ) //not edges
+ point[0] = Math.clamp(x,0,1);
+ else
+ point[0] = s == 0 ? 0 : 1;
+ point[1] = 1.0 - Math.clamp(y,0,1);
+ points.sort(function(a,b){ return a[0] - b[0]; });
+ this.selected = points.indexOf(point);
+ this.must_update = true;
+ }
+ }
+
+ CurveEditor.prototype.onMouseUp = function( localpos, graphcanvas )
+ {
+ this.selected = -1;
+ return false;
+ }
+
+ CurveEditor.prototype.getCloserPoint = function(pos, max_dist)
+ {
+ var points = this.points;
+ if(!points)
+ return -1;
+ max_dist = max_dist || 30;
+ var w = (this.size[0] - this.margin * 2);
+ var h = (this.size[1] - this.margin * 2);
+ var num = points.length;
+ var p2 = [0,0];
+ var min_dist = 1000000;
+ var closest = -1;
+ var last_valid = -1;
+ for(var i = 0; i < num; ++i)
+ {
+ var p = points[i];
+ p2[0] = p[0] * w;
+ p2[1] = (1.0 - p[1]) * h;
+ if(p2[0] < pos[0])
+ last_valid = i;
+ var dist = vec2.distance(pos,p2);
+ if(dist > min_dist || dist > max_dist)
+ continue;
+ closest = i;
+ min_dist = dist;
+ }
+ return closest;
+ }
+
+ LiteGraph.CurveEditor = CurveEditor;
+
//used to create nodes from wrapping functions
LiteGraph.getParameterNames = function(func) {
return (func + "")
diff --git a/src/nodes/geometry.js b/src/nodes/geometry.js
index 517d00b09..bfaa02101 100644
--- a/src/nodes/geometry.js
+++ b/src/nodes/geometry.js
@@ -21,23 +21,36 @@
}
function LGraphPoints3D() {
+
+ this.addInput("obj", "");
+ this.addInput("radius", "number");
+
this.addOutput("out", "geometry");
- this.addOutput("points", "array");
+ this.addOutput("points", "[vec3]");
this.properties = {
radius: 1,
num_points: 4096,
+ generate_normals: true,
regular: false,
- mode: LGraphPoints3D.SPHERE
+ mode: LGraphPoints3D.SPHERE,
+ force_update: false
};
this.points = new Float32Array( this.properties.num_points * 3 );
+ this.normals = new Float32Array( this.properties.num_points * 3 );
this.must_update = true;
this.version = 0;
+ var that = this;
+ this.addWidget("button","update",null, function(){ that.must_update = true; });
+
this.geometry = {
vertices: null,
_id: generateGeometryId()
}
+
+ this._old_obj = null;
+ this._last_radius = null;
}
global.LGraphPoints3D = LGraphPoints3D;
@@ -50,7 +63,10 @@
LGraphPoints3D.HEMISPHERE = 12;
LGraphPoints3D.INSIDE_SPHERE = 13;
- LGraphPoints3D.MODE_VALUES = { "rectangle":LGraphPoints3D.RECTANGLE, "circle":LGraphPoints3D.CIRCLE, "cube":LGraphPoints3D.CUBE, "sphere":LGraphPoints3D.SPHERE, "hemisphere":LGraphPoints3D.HEMISPHERE, "inside_sphere":LGraphPoints3D.INSIDE_SPHERE };
+ LGraphPoints3D.OBJECT = 20;
+ LGraphPoints3D.OBJECT_UNIFORMLY = 21;
+
+ LGraphPoints3D.MODE_VALUES = { "rectangle":LGraphPoints3D.RECTANGLE, "circle":LGraphPoints3D.CIRCLE, "cube":LGraphPoints3D.CUBE, "sphere":LGraphPoints3D.SPHERE, "hemisphere":LGraphPoints3D.HEMISPHERE, "inside_sphere":LGraphPoints3D.INSIDE_SPHERE, "object":LGraphPoints3D.OBJECT, "object_uniformly":LGraphPoints3D.OBJECT_UNIFORMLY };
LGraphPoints3D.widgets_info = {
mode: { widget: "combo", values: LGraphPoints3D.MODE_VALUES }
@@ -65,23 +81,71 @@
}
LGraphPoints3D.prototype.onExecute = function() {
- if(this.must_update)
+
+ var obj = this.getInputData(0);
+ if( obj != this._old_obj || (obj && obj._version != this._old_obj_version) )
+ {
+ this._old_obj = obj;
+ this.must_update = true;
+ }
+
+ var radius = this.getInputData(1);
+ if(radius == null)
+ radius = this.properties.radius;
+ if( this._last_radius != radius )
+ {
+ this._last_radius = radius;
+ this.must_update = true;
+ }
+
+ if(this.must_update || this.properties.force_update )
{
this.must_update = false;
this.updatePoints();
}
this.geometry.vertices = this.points;
+ this.geometry.normals = this.normals;
this.geometry._version = this.version;
this.setOutputData( 0, this.geometry );
}
- LGraphPoints3D.generatePoints = function( radius, num_points, mode, points, regular )
+ LGraphPoints3D.prototype.updatePoints = function() {
+ var num_points = this.properties.num_points|0;
+ if(num_points < 1)
+ num_points = 1;
+
+ if(!this.points || this.points.length != num_points * 3)
+ this.points = new Float32Array( num_points * 3 );
+
+ if(this.properties.generate_normals)
+ {
+ if (!this.normals || this.normals.length != this.points.length)
+ this.normals = new Float32Array( this.points.length );
+ }
+ else
+ this.normals = null;
+
+ var radius = this._last_radius || this.properties.radius;
+ var mode = this.properties.mode;
+
+ var obj = this.getInputData(0);
+ this._old_obj_version = obj ? obj._version : null;
+
+ this.points = LGraphPoints3D.generatePoints( radius, num_points, mode, this.points, this.normals, this.properties.regular, obj );
+
+ this.version++;
+ }
+
+ //global
+ LGraphPoints3D.generatePoints = function( radius, num_points, mode, points, normals, regular, obj )
{
var size = num_points * 3;
if(!points || points.length != size)
points = new Float32Array( size );
+ var temp = new Float32Array(3);
+ var UP = new Float32Array([0,1,0]);
if(regular)
{
@@ -97,11 +161,15 @@
points[pos+2] = ((j/side) - 0.5) * radius * 2;
}
points = new Float32Array( points.subarray(0,side*side*3) );
+ if(normals)
+ {
+ for(var i = 0; i < normals.length; i+=3)
+ normals.set(i, UP);
+ }
}
else if( mode == LGraphPoints3D.SPHERE)
{
var side = Math.floor(Math.sqrt(num_points));
- var temp = vec3.create();
for(var i = 0; i < side; ++i)
for(var j = 0; j < side; ++j)
{
@@ -112,8 +180,11 @@
points[pos+2] = temp[2];
}
points = new Float32Array( points.subarray(0,side*side*3) );
+ if(normals)
+ LGraphPoints3D.generateSphericalNormals( points, normals );
}
else if( mode == LGraphPoints3D.CIRCLE)
+ {
for(var i = 0; i < size; i+=3)
{
var angle = 2 * Math.PI * (i/size);
@@ -121,75 +192,75 @@
points[i+1] = 0;
points[i+2] = Math.sin( angle ) * radius;
}
+ if(normals)
+ {
+ for(var i = 0; i < normals.length; i+=3)
+ normals.set(i, UP);
+ }
+ }
}
- else
+ else //non regular
{
if( mode == LGraphPoints3D.RECTANGLE)
+ {
for(var i = 0; i < size; i+=3)
{
points[i] = (Math.random() - 0.5) * radius * 2;
points[i+1] = 0;
points[i+2] = (Math.random() - 0.5) * radius * 2;
}
+ if(normals)
+ {
+ for(var i = 0; i < normals.length; i+=3)
+ normals.set(i, UP);
+ }
+ }
else if( mode == LGraphPoints3D.CUBE)
+ {
for(var i = 0; i < size; i+=3)
{
points[i] = (Math.random() - 0.5) * radius * 2;
points[i+1] = (Math.random() - 0.5) * radius * 2;
points[i+2] = (Math.random() - 0.5) * radius * 2;
}
+ if(normals)
+ {
+ for(var i = 0; i < normals.length; i+=3)
+ normals.set(i, UP);
+ }
+ }
else if( mode == LGraphPoints3D.SPHERE)
- for(var i = 0; i < size; i+=3)
- {
- var r1 = Math.random();
- var r2 = Math.random();
- var x = 2 * Math.cos( 2 * Math.PI * r1 ) * Math.sqrt( r2 * (1-r2) );
- var y = 1 - 2 * r2;
- var z = 2 * Math.sin( 2 * Math.PI * r1 ) * Math.sqrt( r2 * (1-r2) );
- points[i] = x * radius;
- points[i+1] = y * radius;
- points[i+2] = z * radius;
- }
+ {
+ LGraphPoints3D.generateSphere( points, size, radius );
+ if(normals)
+ LGraphPoints3D.generateSphericalNormals( points, normals );
+ }
else if( mode == LGraphPoints3D.HEMISPHERE)
- for(var i = 0; i < size; i+=3)
- {
- var r1 = Math.random();
- var r2 = Math.random();
- var x = Math.cos( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
- var y = r2;
- var z = Math.sin( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
- points[i] = x * radius;
- points[i+1] = y * radius;
- points[i+2] = z * radius;
- }
+ {
+ LGraphPoints3D.generateHemisphere( points, size, radius );
+ if(normals)
+ LGraphPoints3D.generateSphericalNormals( points, normals );
+ }
else if( mode == LGraphPoints3D.CIRCLE)
- for(var i = 0; i < size; i+=3)
- {
- var r1 = Math.random();
- var r2 = Math.random();
- var x = Math.cos( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
- var y = r2;
- var z = Math.sin( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
- points[i] = x * radius;
- points[i+1] = 0;
- points[i+2] = z * radius;
- }
+ {
+ LGraphPoints3D.generateInsideCircle( points, size, radius );
+ if(normals)
+ LGraphPoints3D.generateSphericalNormals( points, normals );
+ }
else if( mode == LGraphPoints3D.INSIDE_SPHERE)
- for(var i = 0; i < size; i+=3)
- {
- var u = Math.random();
- var v = Math.random();
- var theta = u * 2.0 * Math.PI;
- var phi = Math.acos(2.0 * v - 1.0);
- var r = Math.cbrt(Math.random()) * radius;
- var sinTheta = Math.sin(theta);
- var cosTheta = Math.cos(theta);
- var sinPhi = Math.sin(phi);
- var cosPhi = Math.cos(phi);
- points[i] = r * sinPhi * cosTheta;
- points[i+1] = r * sinPhi * sinTheta;
- points[i+2] = r * cosPhi;
- }
+ {
+ LGraphPoints3D.generateInsideSphere( points, size, radius );
+ if(normals)
+ LGraphPoints3D.generateSphericalNormals( points, normals );
+ }
+ else if( mode == LGraphPoints3D.OBJECT)
+ {
+ LGraphPoints3D.generateFromObject( points, normals, size, obj, false );
+ }
+ else if( mode == LGraphPoints3D.OBJECT_UNIFORMLY)
+ {
+ LGraphPoints3D.generateFromObject( points, normals, size, obj, true );
+ }
else
console.warn("wrong mode in LGraphPoints3D");
}
@@ -197,61 +268,613 @@
return points;
}
- LGraphPoints3D.prototype.updatePoints = function() {
- var num_points = this.properties.num_points|0;
- if(num_points < 1)
- num_points = 1;
- if(this.points.length != num_points * 3)
- this.points = new Float32Array( num_points * 3 );
+ LGraphPoints3D.generateSphericalNormals = function(points, normals)
+ {
+ var temp = new Float32Array(3);
+ for(var i = 0; i < normals.length; i+=3)
+ {
+ temp[0] = points[i];
+ temp[1] = points[i+1];
+ temp[2] = points[i+2];
+ vec3.normalize(temp,temp);
+ normals.set(temp,i);
+ }
+ }
- var points = this.points;
- var radius = this.properties.radius;
- var mode = this.properties.mode;
+ LGraphPoints3D.generateSphere = function (points, size, radius)
+ {
+ for(var i = 0; i < size; i+=3)
+ {
+ var r1 = Math.random();
+ var r2 = Math.random();
+ var x = 2 * Math.cos( 2 * Math.PI * r1 ) * Math.sqrt( r2 * (1-r2) );
+ var y = 1 - 2 * r2;
+ var z = 2 * Math.sin( 2 * Math.PI * r1 ) * Math.sqrt( r2 * (1-r2) );
+ points[i] = x * radius;
+ points[i+1] = y * radius;
+ points[i+2] = z * radius;
+ }
+ }
- this.points = LGraphPoints3D.generatePoints( radius, num_points, mode, this.points, this.properties.regular );
+ LGraphPoints3D.generateHemisphere = function (points, size, radius)
+ {
+ for(var i = 0; i < size; i+=3)
+ {
+ var r1 = Math.random();
+ var r2 = Math.random();
+ var x = Math.cos( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
+ var y = r2;
+ var z = Math.sin( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
+ points[i] = x * radius;
+ points[i+1] = y * radius;
+ points[i+2] = z * radius;
+ }
+ }
- this.version++;
+ LGraphPoints3D.generateInsideCircle = function (points, size, radius)
+ {
+ for(var i = 0; i < size; i+=3)
+ {
+ var r1 = Math.random();
+ var r2 = Math.random();
+ var x = Math.cos( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
+ var y = r2;
+ var z = Math.sin( 2 * Math.PI * r1 ) * Math.sqrt(1 - r2*r2 );
+ points[i] = x * radius;
+ points[i+1] = 0;
+ points[i+2] = z * radius;
+ }
+ }
+
+ LGraphPoints3D.generateInsideSphere = function (points, size, radius)
+ {
+ for(var i = 0; i < size; i+=3)
+ {
+ var u = Math.random();
+ var v = Math.random();
+ var theta = u * 2.0 * Math.PI;
+ var phi = Math.acos(2.0 * v - 1.0);
+ var r = Math.cbrt(Math.random()) * radius;
+ var sinTheta = Math.sin(theta);
+ var cosTheta = Math.cos(theta);
+ var sinPhi = Math.sin(phi);
+ var cosPhi = Math.cos(phi);
+ points[i] = r * sinPhi * cosTheta;
+ points[i+1] = r * sinPhi * sinTheta;
+ points[i+2] = r * cosPhi;
+ }
+ }
+
+ function findRandomTriangle( areas, f )
+ {
+ var l = areas.length;
+ var imin = 0;
+ var imid = 0;
+ var imax = l;
+
+ if(l == 0)
+ return -1;
+ if(l == 1)
+ return 0;
+ //dichotimic search
+ while (imax >= imin)
+ {
+ imid = ((imax + imin)*0.5)|0;
+ var t = areas[ imid ];
+ if( t == f )
+ return imid;
+ if( imin == (imax - 1) )
+ return imin;
+ if (t < f)
+ imin = imid;
+ else
+ imax = imid;
+ }
+ return imid;
+ }
+
+ LGraphPoints3D.generateFromObject = function( points, normals, size, obj, evenly )
+ {
+ if(!obj)
+ return;
+
+ var vertices = null;
+ var mesh_normals = null;
+ var indices = null;
+ var areas = null;
+ if( obj.constructor === GL.Mesh )
+ {
+ vertices = obj.vertexBuffers.vertices.data;
+ mesh_normals = obj.vertexBuffers.normals ? obj.vertexBuffers.normals.data : null;
+ indices = obj.indexBuffers.indices ? obj.indexBuffers.indices.data : null;
+ if(!indices)
+ indices = obj.indexBuffers.triangles ? obj.indexBuffers.triangles.data : null;
+ }
+ if(!vertices)
+ return null;
+ var num_triangles = indices ? indices.length / 3 : vertices.length / (3*3);
+ var total_area = 0; //sum of areas of all triangles
+
+ if(evenly)
+ {
+ areas = new Float32Array(num_triangles); //accum
+ for(var i = 0; i < num_triangles; ++i)
+ {
+ if(indices)
+ {
+ a = indices[i*3]*3;
+ b = indices[i*3+1]*3;
+ c = indices[i*3+2]*3;
+ }
+ else
+ {
+ a = i*9;
+ b = i*9+3;
+ c = i*9+6;
+ }
+ var P1 = vertices.subarray(a,a+3);
+ var P2 = vertices.subarray(b,b+3);
+ var P3 = vertices.subarray(c,c+3);
+ var aL = vec3.distance( P1, P2 );
+ var bL = vec3.distance( P2, P3 );
+ var cL = vec3.distance( P3, P1 );
+ var s = (aL + bL+ cL) / 2;
+ total_area += Math.sqrt(s * (s - aL) * (s - bL) * (s - cL));
+ areas[i] = total_area;
+ }
+ for(var i = 0; i < num_triangles; ++i) //normalize
+ areas[i] /= total_area;
+ }
+
+ for(var i = 0; i < size; i+=3)
+ {
+ var r = Math.random();
+ var index = evenly ? findRandomTriangle( areas, r ) : Math.floor(r * num_triangles );
+ //get random triangle
+ var a = 0;
+ var b = 0;
+ var c = 0;
+ if(indices)
+ {
+ a = indices[index*3]*3;
+ b = indices[index*3+1]*3;
+ c = indices[index*3+2]*3;
+ }
+ else
+ {
+ a = index*9;
+ b = index*9+3;
+ c = index*9+6;
+ }
+ var s = Math.random();
+ var t = Math.random();
+ var sqrt_s = Math.sqrt(s);
+ var af = 1 - sqrt_s;
+ var bf = sqrt_s * ( 1 - t);
+ var cf = t * sqrt_s;
+ points[i] = af * vertices[a] + bf*vertices[b] + cf*vertices[c];
+ points[i+1] = af * vertices[a+1] + bf*vertices[b+1] + cf*vertices[c+1];
+ points[i+2] = af * vertices[a+2] + bf*vertices[b+2] + cf*vertices[c+2];
+ if(normals && mesh_normals)
+ {
+ normals[i] = af * mesh_normals[a] + bf*mesh_normals[b] + cf*mesh_normals[c];
+ normals[i+1] = af * mesh_normals[a+1] + bf*mesh_normals[b+1] + cf*mesh_normals[c+1];
+ normals[i+2] = af * mesh_normals[a+2] + bf*mesh_normals[b+2] + cf*mesh_normals[c+2];
+ var N = normals.subarray(i,i+3);
+ vec3.normalize(N,N);
+ }
+ }
}
LiteGraph.registerNodeType( "geometry/points3D", LGraphPoints3D );
- function LGraphToGeometry() {
- this.addInput("mesh", "mesh");
- this.addOutput("out", "geometry");
- this.geometry = {};
- this.last_mesh = null;
+
+ function LGraphPointsToInstances() {
+ this.addInput("points", "geometry");
+ this.addOutput("instances", "[mat4]");
+ this.properties = {
+ mode: 1
+ };
+
+ this.must_update = true;
+ this.matrices = [];
}
- LGraphToGeometry.title = "to geometry";
- LGraphToGeometry.desc = "converts a mesh to geometry";
+ LGraphPointsToInstances.NORMAL = 0;
+ LGraphPointsToInstances.VERTICAL = 1;
+ LGraphPointsToInstances.SPHERICAL = 2;
+ LGraphPointsToInstances.RANDOM = 3;
+ LGraphPointsToInstances.RANDOM_VERTICAL = 4;
- LGraphToGeometry.prototype.onExecute = function() {
- var mesh = this.getInputData(0);
- if(!mesh)
+ LGraphPointsToInstances.modes = {"normal":0,"vertical":1,"spherical":2,"random":3,"random_vertical":4};
+ LGraphPointsToInstances.widgets_info = {
+ mode: { widget: "combo", values: LGraphPointsToInstances.modes }
+ };
+
+ LGraphPointsToInstances.title = "points to inst";
+
+ LGraphPointsToInstances.prototype.onExecute = function()
+ {
+ var geo = this.getInputData(0);
+ if( !geo )
+ {
+ this.setOutputData(0,null);
+ return;
+ }
+
+ if( !this.isOutputConnected(0) )
return;
- if(mesh != this.last_mesh)
- {
- this.last_mesh = mesh;
- for(i in mesh.vertexBuffers)
- {
- var buffer = mesh.vertexBuffers[i];
- this.geometry[i] = buffer.data
- }
- if(mesh.indexBuffers["triangles"])
- this.geometry.indices = mesh.indexBuffers["triangles"].data;
+ if( geo._version != this._version || geo._id != this._geometry_id )
+ this.updateInstances( geo );
- this.geometry._id = generateGeometryId();
- this.geometry._version = 0;
+ this.setOutputData( 0, this.matrices );
+ }
+
+ LGraphPointsToInstances.prototype.updateInstances = function( geometry )
+ {
+ var vertices = geometry.vertices;
+ if(!vertices)
+ return null;
+ var normals = geometry.normals;
+
+ var matrices = this.matrices;
+ var num_points = vertices.length / 3;
+ if( matrices.length != num_points)
+ matrices.length = num_points;
+ var identity = mat4.create();
+ var temp = vec3.create();
+ var zero = vec3.create();
+ var UP = vec3.fromValues(0,1,0);
+ var FRONT = vec3.fromValues(0,0,-1);
+ var RIGHT = vec3.fromValues(1,0,0);
+ var R = quat.create();
+
+ var front = vec3.create();
+ var right = vec3.create();
+ var top = vec3.create();
+
+ for(var i = 0; i < vertices.length; i += 3)
+ {
+ var index = i/3;
+ var m = matrices[index];
+ if(!m)
+ m = matrices[index] = mat4.create();
+ m.set( identity );
+ var point = vertices.subarray(i,i+3);
+
+ switch(this.properties.mode)
+ {
+ case LGraphPointsToInstances.NORMAL:
+ mat4.setTranslation( m, point );
+ if(normals)
+ {
+ var normal = normals.subarray(i,i+3);
+ top.set( normal );
+ vec3.normalize( top, top );
+ vec3.cross( right, FRONT, top );
+ vec3.normalize( right, right );
+ vec3.cross( front, right, top );
+ vec3.normalize( front, front );
+ m.set(right,0);
+ m.set(top,4);
+ m.set(front,8);
+ mat4.setTranslation( m, point );
+ }
+ break;
+ case LGraphPointsToInstances.VERTICAL:
+ mat4.setTranslation( m, point );
+ break;
+ case LGraphPointsToInstances.SPHERICAL:
+ front.set( point );
+ vec3.normalize( front, front );
+ vec3.cross( right, UP, front );
+ vec3.normalize( right, right );
+ vec3.cross( top, front, right );
+ vec3.normalize( top, top );
+ m.set(right,0);
+ m.set(top,4);
+ m.set(front,8);
+ mat4.setTranslation( m, point );
+ break;
+ case LGraphPointsToInstances.RANDOM:
+ temp[0] = Math.random()*2 - 1;
+ temp[1] = Math.random()*2 - 1;
+ temp[2] = Math.random()*2 - 1;
+ vec3.normalize( temp, temp );
+ quat.setAxisAngle( R, temp, Math.random() * 2 * Math.PI );
+ mat4.fromQuat(m, R);
+ mat4.setTranslation( m, point );
+ break;
+ case LGraphPointsToInstances.RANDOM_VERTICAL:
+ quat.setAxisAngle( R, UP, Math.random() * 2 * Math.PI );
+ mat4.fromQuat(m, R);
+ mat4.setTranslation( m, point );
+ break;
+ }
+ }
+
+ this._version = geometry._version;
+ this._geometry_id = geometry._id;
+ }
+
+ LiteGraph.registerNodeType( "geometry/points_to_instances", LGraphPointsToInstances );
+
+
+ function LGraphGeometryTransform() {
+ this.addInput("in", "geometry,[mat4]");
+ this.addInput("mat4", "mat4");
+ this.addOutput("out", "geometry");
+ this.properties = {};
+
+ this.geometry = {
+ type: "triangles",
+ vertices: null,
+ _id: generateGeometryId()
+ };
+
+ this._last_geometry_id = -1;
+ this._last_version = -1;
+ this._last_key = "";
+
+ this.must_update = true;
+ }
+
+ LGraphGeometryTransform.title = "Transform";
+
+ LGraphGeometryTransform.prototype.onExecute = function() {
+
+ var input = this.getInputData(0);
+ var model = this.getInputData(1);
+
+ if(!input)
+ return;
+
+ //array of matrices
+ if(input.constructor === Array)
+ {
+ if(input.length == 0)
+ return;
+ this.outputs[0].type = "[mat4]";
+ if( !this.isOutputConnected(0) )
+ return;
+
+ if(!model)
+ {
+ this.setOutputData(0,input);
+ return;
+ }
+
+ if(!this._output)
+ this._output = new Array();
+ if(this._output.length != input.length)
+ this._output.length = input.length;
+ for(var i = 0; i < input.length; ++i)
+ {
+ var m = this._output[i];
+ if(!m)
+ m = this._output[i] = mat4.create();
+ mat4.multiply(m,input[i],model);
+ }
+ this.setOutputData(0,this._output);
+ return;
+ }
+
+ //geometry
+ if(!input.vertices || !input.vertices.length)
+ return;
+ var geo = input;
+ this.outputs[0].type = "geometry";
+ if( !this.isOutputConnected(0) )
+ return;
+ if(!model)
+ {
+ this.setOutputData(0,geo);
+ return;
+ }
+
+ var key = typedArrayToArray(model).join(",");
+
+ if( this.must_update || geo._id != this._last_geometry_id || geo._version != this._last_version || key != this._last_key )
+ {
+ this.updateGeometry(geo, model);
+ this._last_key = key;
+ this._last_version = geo._version;
+ this._last_geometry_id = geo._id;
+ this.must_update = false;
}
this.setOutputData(0,this.geometry);
- if(this.geometry)
- this.setOutputData(1,this.geometry.vertices);
}
- LiteGraph.registerNodeType( "geometry/toGeometry", LGraphToGeometry );
+ LGraphGeometryTransform.prototype.updateGeometry = function(geometry, model) {
+ var old_vertices = geometry.vertices;
+ var vertices = this.geometry.vertices;
+ if( !vertices || vertices.length != old_vertices.length )
+ vertices = this.geometry.vertices = new Float32Array( old_vertices.length );
+ var temp = vec3.create();
+
+ for(var i = 0, l = vertices.length; i < l; i+=3)
+ {
+ temp[0] = old_vertices[i]; temp[1] = old_vertices[i+1]; temp[2] = old_vertices[i+2];
+ mat4.multiplyVec3( temp, model, temp );
+ vertices[i] = temp[0]; vertices[i+1] = temp[1]; vertices[i+2] = temp[2];
+ }
+
+ if(geometry.normals)
+ {
+ if( !this.geometry.normals || this.geometry.normals.length != geometry.normals.length )
+ this.geometry.normals = new Float32Array( geometry.normals.length );
+ var normals = this.geometry.normals;
+ var normal_model = mat4.invert(mat4.create(), model);
+ if(normal_model)
+ mat4.transpose(normal_model, normal_model);
+ var old_normals = geometry.normals;
+ for(var i = 0, l = normals.length; i < l; i+=3)
+ {
+ temp[0] = old_normals[i]; temp[1] = old_normals[i+1]; temp[2] = old_normals[i+2];
+ mat4.multiplyVec3( temp, normal_model, temp );
+ normals[i] = temp[0]; normals[i+1] = temp[1]; normals[i+2] = temp[2];
+ }
+ }
+
+ this.geometry.type = geometry.type;
+ this.geometry._version++;
+ }
+
+ LiteGraph.registerNodeType( "geometry/transform", LGraphGeometryTransform );
+
+
+ function LGraphGeometryPolygon() {
+ this.addInput("sides", "number");
+ this.addInput("radius", "number");
+ this.addOutput("out", "geometry");
+ this.properties = { sides: 6, radius: 1 }
+
+ this.geometry = {
+ type: "line_loop",
+ vertices: null,
+ _id: generateGeometryId()
+ };
+ this.geometry_id = -1;
+ this.version = -1;
+ this.must_update = true;
+
+ this.last_info = { sides: -1, radius: -1 };
+ }
+
+ LGraphGeometryPolygon.title = "Polygon";
+
+ LGraphGeometryPolygon.prototype.onExecute = function() {
+
+ if( !this.isOutputConnected(0) )
+ return;
+
+ var sides = this.getInputOrProperty("sides");
+ var radius = this.getInputOrProperty("radius");
+ sides = Math.max(3,sides)|0;
+
+ //update
+ if( this.last_info.sides != sides || this.last_info.radius != radius )
+ this.updateGeometry(sides, radius);
+
+ this.setOutputData(0,this.geometry);
+ }
+
+ LGraphGeometryPolygon.prototype.updateGeometry = function(sides, radius) {
+ var num = 3*sides;
+ var vertices = this.geometry.vertices;
+ if( !vertices || vertices.length != num )
+ vertices = this.geometry.vertices = new Float32Array( 3*sides );
+ var delta = (Math.PI * 2) / sides;
+ for(var i = 0; i < sides; ++i)
+ {
+ var angle = delta * -i;
+ var x = Math.cos( angle ) * radius;
+ var y = 0;
+ var z = Math.sin( angle ) * radius;
+ vertices[i*3] = x;
+ vertices[i*3+1] = y;
+ vertices[i*3+2] = z;
+ }
+ this.geometry._id = ++this.geometry_id;
+ this.geometry._version = ++this.version;
+ this.last_info.sides = sides;
+ this.last_info.radius = radius;
+ }
+
+ LiteGraph.registerNodeType( "geometry/polygon", LGraphGeometryPolygon );
+
+
+ function LGraphGeometryExtrude() {
+
+ this.addInput("", "geometry");
+ this.addOutput("", "geometry");
+ this.properties = { top_cap: true, bottom_cap: true, offset: [0,100,0] };
+ this.version = -1;
+
+ this._last_geo_version = -1;
+ this._must_update = true;
+ }
+
+ LGraphGeometryExtrude.title = "extrude";
+
+ LGraphGeometryExtrude.prototype.onPropertyChanged = function(name, value)
+ {
+ this._must_update = true;
+ }
+
+ LGraphGeometryExtrude.prototype.onExecute = function()
+ {
+ var geo = this.getInputData(0);
+ if( !geo || !this.isOutputConnected(0) )
+ return;
+
+ if(geo.version != this._last_geo_version || this._must_update)
+ {
+ this._geo = this.extrudeGeometry( geo, this._geo );
+ if(this._geo)
+ this._geo.version = this.version++;
+ this._must_update = false;
+ }
+
+ this.setOutputData(0, this._geo);
+ }
+
+ LGraphGeometryExtrude.prototype.extrudeGeometry = function( geo )
+ {
+ //for every pair of vertices
+ var vertices = geo.vertices;
+ var num_points = vertices.length / 3;
+
+ var tempA = vec3.create();
+ var tempB = vec3.create();
+ var tempC = vec3.create();
+ var tempD = vec3.create();
+ var offset = new Float32Array( this.properties.offset );
+
+ if(geo.type == "line_loop")
+ {
+ var new_vertices = new Float32Array( num_points * 6 * 3 ); //every points become 6 ( caps not included )
+ var npos = 0;
+ for(var i = 0, l = vertices.length; i < l; i += 3)
+ {
+ tempA[0] = vertices[i]; tempA[1] = vertices[i+1]; tempA[2] = vertices[i+2];
+
+ if( i+3 < l ) //loop
+ {
+ tempB[0] = vertices[i+3]; tempB[1] = vertices[i+4]; tempB[2] = vertices[i+5];
+ }
+ else
+ {
+ tempB[0] = vertices[0]; tempB[1] = vertices[1]; tempB[2] = vertices[2];
+ }
+
+ vec3.add( tempC, tempA, offset );
+ vec3.add( tempD, tempB, offset );
+
+ new_vertices.set( tempA, npos ); npos += 3;
+ new_vertices.set( tempB, npos ); npos += 3;
+ new_vertices.set( tempC, npos ); npos += 3;
+
+ new_vertices.set( tempB, npos ); npos += 3;
+ new_vertices.set( tempD, npos ); npos += 3;
+ new_vertices.set( tempC, npos ); npos += 3;
+ }
+ }
+
+ var out_geo = {
+ _id: generateGeometryId(),
+ type: "triangles",
+ vertices: new_vertices
+ };
+
+ return out_geo;
+ }
+
+ LiteGraph.registerNodeType( "geometry/extrude", LGraphGeometryExtrude );
+
function LGraphGeometryEval() {
this.addInput("in", "geometry");
@@ -530,40 +1153,55 @@ function LGraphGeometryDisplace() {
if (typeof GL == "undefined") //LiteGL RELATED **********************************************
return;
- function LGraphRenderGeometry() {
+ function LGraphToGeometry() {
+ this.addInput("mesh", "mesh");
+ this.addOutput("out", "geometry");
+
+ this.geometry = {};
+ this.last_mesh = null;
+ }
+
+ LGraphToGeometry.title = "to geometry";
+ LGraphToGeometry.desc = "converts a mesh to geometry";
+
+ LGraphToGeometry.prototype.onExecute = function() {
+ var mesh = this.getInputData(0);
+ if(!mesh)
+ return;
+
+ if(mesh != this.last_mesh)
+ {
+ this.last_mesh = mesh;
+ for(i in mesh.vertexBuffers)
+ {
+ var buffer = mesh.vertexBuffers[i];
+ this.geometry[i] = buffer.data
+ }
+ if(mesh.indexBuffers["triangles"])
+ this.geometry.indices = mesh.indexBuffers["triangles"].data;
+
+ this.geometry._id = generateGeometryId();
+ this.geometry._version = 0;
+ }
+
+ this.setOutputData(0,this.geometry);
+ if(this.geometry)
+ this.setOutputData(1,this.geometry.vertices);
+ }
+
+ LiteGraph.registerNodeType( "geometry/toGeometry", LGraphToGeometry );
+
+ function LGraphGeometryToMesh() {
this.addInput("in", "geometry");
- this.addInput("mat4", "mat4");
- this.addInput("tex", "texture");
this.addOutput("mesh", "mesh");
-
- this.properties = {
- enabled: true,
- primitive: GL.TRIANGLES,
- additive: false,
- color: [1,1,1],
- opacity: 1
- };
-
- this.color = vec4.create([1,1,1,1]);
- this.uniforms = {
- u_color: this.color
- };
-
+ this.properties = {};
this.version = -1;
this.mesh = null;
}
- LGraphRenderGeometry.title = "render";
- LGraphRenderGeometry.desc = "renders a geometry";
+ LGraphGeometryToMesh.title = "Geo to Mesh";
- LGraphRenderGeometry.PRIMITIVE_VALUES = { "points":GL.POINTS, "lines":GL.LINES, "line_loop":GL.LINE_LOOP,"line_strip":GL.LINE_STRIP, "triangles":GL.TRIANGLES, "triangle_fan":GL.TRIANGLE_FAN, "triangle_strip":GL.TRIANGLE_STRIP };
-
- LGraphRenderGeometry.widgets_info = {
- primitive: { widget: "combo", values: LGraphRenderGeometry.PRIMITIVE_VALUES },
- color: { widget: "color" }
- };
-
- LGraphRenderGeometry.prototype.updateMesh = function(geometry)
+ LGraphGeometryToMesh.prototype.updateMesh = function(geometry)
{
if(!this.mesh)
this.mesh = new GL.Mesh();
@@ -594,21 +1232,73 @@ function LGraphGeometryDisplace() {
this.mesh.addBuffer( i, mesh_buffer );
}
+ if(this.mesh.vertexBuffers.normals &&this.mesh.vertexBuffers.normals.data.length != this.mesh.vertexBuffers.vertices.data.length )
+ {
+ var n = new Float32Array([0,1,0]);
+ var normals = new Float32Array( this.mesh.vertexBuffers.vertices.data.length );
+ for(var i = 0; i < normals.length; i+= 3)
+ normals.set( n, i );
+ mesh_buffer = new GL.Buffer( GL.ARRAY_BUFFER, normals, 3 );
+ this.mesh.addBuffer( "normals", mesh_buffer );
+ }
+
+ this.mesh.updateBoundingBox();
this.geometry_id = this.mesh.id = geometry._id;
this.version = this.mesh.version = geometry._version;
return this.mesh;
}
- LGraphRenderGeometry.prototype.onExecute = function() {
-
- if(!this.properties.enabled)
- return;
+ LGraphGeometryToMesh.prototype.onExecute = function() {
var geometry = this.getInputData(0);
if(!geometry)
return;
if( this.version != geometry._version || this.geometry_id != geometry._id )
this.updateMesh( geometry );
+ this.setOutputData(0, this.mesh);
+ }
+
+ LiteGraph.registerNodeType( "geometry/toMesh", LGraphGeometryToMesh );
+
+ function LGraphRenderMesh() {
+ this.addInput("mesh", "mesh");
+ this.addInput("mat4", "mat4");
+ this.addInput("tex", "texture");
+
+ this.properties = {
+ enabled: true,
+ primitive: GL.TRIANGLES,
+ additive: false,
+ color: [1,1,1],
+ opacity: 1
+ };
+
+ this.color = vec4.create([1,1,1,1]);
+ this.model_matrix = mat4.create();
+ this.uniforms = {
+ u_color: this.color,
+ u_model: this.model_matrix
+ };
+ }
+
+ LGraphRenderMesh.title = "Render Mesh";
+ LGraphRenderMesh.desc = "renders a mesh flat";
+
+ LGraphRenderMesh.PRIMITIVE_VALUES = { "points":GL.POINTS, "lines":GL.LINES, "line_loop":GL.LINE_LOOP,"line_strip":GL.LINE_STRIP, "triangles":GL.TRIANGLES, "triangle_fan":GL.TRIANGLE_FAN, "triangle_strip":GL.TRIANGLE_STRIP };
+
+ LGraphRenderMesh.widgets_info = {
+ primitive: { widget: "combo", values: LGraphRenderMesh.PRIMITIVE_VALUES },
+ color: { widget: "color" }
+ };
+
+ LGraphRenderMesh.prototype.onExecute = function() {
+
+ if(!this.properties.enabled)
+ return;
+
+ var mesh = this.getInputData(0);
+ if(!mesh)
+ return;
if(!LiteGraph.LGraphRender.onRequestCameraMatrices)
{
@@ -618,9 +1308,7 @@ function LGraphGeometryDisplace() {
LiteGraph.LGraphRender.onRequestCameraMatrices( view_matrix, projection_matrix,viewprojection_matrix );
var shader = null;
-
var texture = this.getInputData(2);
-
if(texture)
{
shader = gl.shaders["textured"];
@@ -637,6 +1325,7 @@ function LGraphGeometryDisplace() {
this.color.set( this.properties.color );
this.color[3] = this.properties.opacity;
+ var model_matrix = this.model_matrix;
var m = this.getInputData(1);
if(m)
model_matrix.set(m);
@@ -661,12 +1350,93 @@ function LGraphGeometryDisplace() {
}
else
gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
- shader.draw( this.mesh, primitive, "indices" );
+
+ var indices = "indices";
+ if( mesh.indexBuffers.triangles )
+ indices = "triangles";
+ shader.draw( mesh, primitive, indices );
gl.disable( gl.BLEND );
gl.depthMask( true );
}
- LiteGraph.registerNodeType( "geometry/render", LGraphRenderGeometry );
+ LiteGraph.registerNodeType( "geometry/render_mesh", LGraphRenderMesh );
+
+ //**************************
+
+
+ function LGraphGeometryPrimitive() {
+ this.addInput("size", "number");
+ this.addOutput("out", "mesh");
+ this.properties = { type: 1, size: 1, subdivisions: 32 };
+
+ this.version = (Math.random() * 100000)|0;
+ this.last_info = { type: -1, size: -1, subdivisions: -1 };
+ }
+
+ LGraphGeometryPrimitive.title = "Primitive";
+
+ LGraphGeometryPrimitive.VALID = { "CUBE":1, "PLANE":2, "CYLINDER":3, "SPHERE":4, "CIRCLE":5, "HEMISPHERE":6, "ICOSAHEDRON":7, "CONE":8, "QUAD":9 };
+ LGraphGeometryPrimitive.widgets_info = {
+ type: { widget: "combo", values: LGraphGeometryPrimitive.VALID }
+ };
+
+ LGraphGeometryPrimitive.prototype.onExecute = function() {
+
+ if( !this.isOutputConnected(0) )
+ return;
+
+ var size = this.getInputOrProperty("size");
+
+ //update
+ if( this.last_info.type != this.properties.type || this.last_info.size != size || this.last_info.subdivisions != this.properties.subdivisions )
+ this.updateMesh( this.properties.type, size, this.properties.subdivisions );
+
+ this.setOutputData(0,this._mesh);
+ }
+
+ LGraphGeometryPrimitive.prototype.updateMesh = function(type, size, subdivisions)
+ {
+ subdivisions = Math.max(0,subdivisions)|0;
+
+ switch (type)
+ {
+ case 1: //CUBE:
+ this._mesh = GL.Mesh.cube({size: size, normals:true,coords:true});
+ break;
+ case 2: //PLANE:
+ this._mesh = GL.Mesh.plane({size: size, xz: true, detail: subdivisions, normals:true,coords:true});
+ break;
+ case 3: //CYLINDER:
+ this._mesh = GL.Mesh.cylinder({size: size, subdivisions: subdivisions, normals:true,coords:true});
+ break;
+ case 4: //SPHERE:
+ this._mesh = GL.Mesh.sphere({size: size, "long": subdivisions, lat: subdivisions, normals:true,coords:true});
+ break;
+ case 5: //CIRCLE:
+ this._mesh = GL.Mesh.circle({size: size, slices: subdivisions, normals:true, coords:true});
+ break;
+ case 6: //HEMISPHERE:
+ this._mesh = GL.Mesh.sphere({size: size, "long": subdivisions, lat: subdivisions, normals:true, coords:true, hemi: true});
+ break;
+ case 7: //ICOSAHEDRON:
+ this._mesh = GL.Mesh.icosahedron({size: size, subdivisions:subdivisions });
+ break;
+ case 8: //CONE:
+ this._mesh = GL.Mesh.cone({radius: size, height: size, subdivisions:subdivisions });
+ break;
+ case 9: //QUAD:
+ this._mesh = GL.Mesh.plane({size: size, xz: false, detail: subdivisions, normals:true, coords:true });
+ break;
+ }
+
+ this.last_info.type = type;
+ this.last_info.size = size;
+ this.last_info.subdivisions = subdivisions;
+ this._mesh.version = this.version++;
+ }
+
+ LiteGraph.registerNodeType( "geometry/mesh_primitive", LGraphGeometryPrimitive );
+
function LGraphRenderPoints() {
this.addInput("in", "geometry");
@@ -695,6 +1465,9 @@ function LGraphGeometryDisplace() {
this.mesh = null;
}
+ LGraphRenderPoints.title = "renderPoints";
+ LGraphRenderPoints.desc = "render points with a texture";
+
LGraphRenderPoints.widgets_info = {
color: { widget: "color" }
};
@@ -702,7 +1475,7 @@ function LGraphGeometryDisplace() {
LGraphRenderPoints.prototype.updateMesh = function(geometry)
{
var buffer = this.buffer;
- if(!this.buffer || this.buffer.data.length != geometry.vertices.length)
+ if(!this.buffer || !this.buffer.data || this.buffer.data.length != geometry.vertices.length)
this.buffer = new GL.Buffer( GL.ARRAY_BUFFER, geometry.vertices,3,GL.DYNAMIC_DRAW);
else
{
diff --git a/src/nodes/gltextures.js b/src/nodes/gltextures.js
index 76b7fc61b..adfbf1856 100755
--- a/src/nodes/gltextures.js
+++ b/src/nodes/gltextures.js
@@ -10,7 +10,8 @@
LGraphCanvas.link_type_colors["Texture"] = "#987";
function LGraphTexture() {
- this.addOutput("Texture", "Texture");
+ this.addOutput("tex", "Texture");
+ this.addOutput("name", "string");
this.properties = { name: "", filter: true };
this.size = [
LGraphTexture.image_preview_size,
@@ -222,6 +223,8 @@
}
if (!tex) {
+ this.setOutputData( 0, null );
+ this.setOutputData( 1, "" );
return;
}
@@ -233,9 +236,10 @@
tex.setParameter(gl.TEXTURE_MAG_FILTER, gl.LINEAR);
}
- this.setOutputData(0, tex);
+ this.setOutputData( 0, tex );
+ this.setOutputData( 1, tex.fullpath || tex.filename );
- for (var i = 1; i < this.outputs.length; i++) {
+ for (var i = 2; i < this.outputs.length; i++) {
var output = this.outputs[i];
if (!output) {
continue;
@@ -3027,10 +3031,106 @@
}\n\
";
- LiteGraph.registerNodeType(
- "texture/depth_range",
- LGraphTextureDepthRange
- );
+ LiteGraph.registerNodeType( "texture/depth_range", LGraphTextureDepthRange );
+
+
+ // Texture Depth *****************************************
+ function LGraphTextureLinearDepth() {
+ this.addInput("Texture", "Texture");
+ this.addOutput("Texture", "Texture");
+ this.properties = {
+ precision: LGraphTexture.DEFAULT,
+ invert: false
+ };
+ this._uniforms = {
+ u_texture: 0,
+ u_near: 0.1,
+ u_far: 10000
+ };
+ }
+
+ LGraphTextureLinearDepth.widgets_info = {
+ precision: { widget: "combo", values: LGraphTexture.MODE_VALUES }
+ };
+
+ LGraphTextureLinearDepth.title = "Linear Depth";
+ LGraphTextureLinearDepth.desc = "Creates a color texture with linear depth";
+
+ LGraphTextureLinearDepth.prototype.onExecute = function() {
+ if (!this.isOutputConnected(0)) {
+ return;
+ } //saves work
+
+ var tex = this.getInputData(0);
+ if (!tex || (tex.format != gl.DEPTH_COMPONENT && tex.format != gl.DEPTH_STENCIL) ) {
+ return;
+ }
+
+ var precision = this.properties.precision == LGraphTexture.HIGH ? gl.HIGH_PRECISION_FORMAT : gl.UNSIGNED_BYTE;
+
+ if ( !this._temp_texture || this._temp_texture.type != precision || this._temp_texture.width != tex.width || this._temp_texture.height != tex.height ) {
+ this._temp_texture = new GL.Texture(tex.width, tex.height, {
+ type: precision,
+ format: gl.RGB,
+ filter: gl.LINEAR
+ });
+ }
+
+ var uniforms = this._uniforms;
+
+ uniforms.u_near = tex.near_far_planes[0];
+ uniforms.u_far = tex.near_far_planes[1];
+ uniforms.u_invert = this.properties.invert ? 1 : 0;
+
+ gl.disable(gl.BLEND);
+ gl.disable(gl.DEPTH_TEST);
+ var mesh = Mesh.getScreenQuad();
+ if(!LGraphTextureLinearDepth._shader)
+ LGraphTextureLinearDepth._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureLinearDepth.pixel_shader);
+ var shader = LGraphTextureLinearDepth._shader;
+
+ //NEAR AND FAR PLANES
+ var planes = null;
+ if (tex.near_far_planes) {
+ planes = tex.near_far_planes;
+ } else if (window.LS && LS.Renderer._main_camera) {
+ planes = LS.Renderer._main_camera._uniforms.u_camera_planes;
+ } else {
+ planes = [0.1, 1000];
+ } //hardcoded
+ uniforms.u_camera_planes = planes;
+
+ this._temp_texture.drawTo(function() {
+ tex.bind(0);
+ shader.uniforms(uniforms).draw(mesh);
+ });
+
+ this._temp_texture.near_far_planes = planes;
+ this.setOutputData(0, this._temp_texture);
+ };
+
+ LGraphTextureLinearDepth.pixel_shader =
+ "precision highp float;\n\
+ precision highp float;\n\
+ varying vec2 v_coord;\n\
+ uniform sampler2D u_texture;\n\
+ uniform float u_near;\n\
+ uniform float u_far;\n\
+ uniform int u_invert;\n\
+ \n\
+ void main() {\n\
+ float zNear = u_near;\n\
+ float zFar = u_far;\n\
+ float depth = texture2D(u_texture, v_coord).x;\n\
+ depth = depth * 2.0 - 1.0;\n\
+ float f = zNear * (depth + 1.0) / (zFar + zNear - depth * (zFar - zNear));\n\
+ if( u_invert == 1 )\n\
+ f = 1.0 - f;\n\
+ gl_FragColor = vec4(vec3(f),1.0);\n\
+ }\n\
+ ";
+
+ LiteGraph.registerNodeType( "texture/linear_depth", LGraphTextureLinearDepth );
// Texture Blur *****************************************
function LGraphTextureBlur() {
@@ -4155,6 +4255,211 @@ void main(void){\n\
LiteGraph.registerNodeType("texture/lensfx", LGraphLensFX);
+
+ function LGraphTextureCurve() {
+ this.addInput("in", "Texture");
+ this.addOutput("out", "Texture");
+ this.properties = { precision: LGraphTexture.LOW, split_channels: false };
+ this._values = new Uint8Array(256*4);
+ this._values.fill(255);
+ this._curve_texture = null;
+ this._uniforms = { u_texture: 0, u_curve: 1, u_range: 1.0 };
+ this._must_update = true;
+ this._points = {
+ RGB: [[0,0],[1,1]],
+ R: [[0,0],[1,1]],
+ G: [[0,0],[1,1]],
+ B: [[0,0],[1,1]]
+ };
+ this.curve_editor = null;
+ this.addWidget("toggle","Split Channels",false,"split_channels");
+ this.addWidget("combo","Channel","RGB",{ values:["RGB","R","G","B"]});
+ this.curve_offset = 68;
+ this.size = [ 240, 160 ];
+ }
+
+ LGraphTextureCurve.title = "Curve";
+
+ LGraphTextureCurve.prototype.onExecute = function() {
+ var tex = this.getInputData(0);
+ if (!tex) {
+ return;
+ }
+
+ if (!this.isOutputConnected(0)) {
+ return;
+ } //saves work
+
+ var temp = this._temp_texture;
+ if ( !temp || temp.width != tex.width || temp.height != tex.height || temp.type != tex.type ) {
+ temp = this._temp_texture = new GL.Texture( tex.width, tex.height, { type: tex.type, format: gl.RGBA, filter: gl.LINEAR } );
+ }
+
+ var shader = LGraphTextureCurve._shader;
+ if (!shader) {
+ shader = LGraphTextureCurve._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureCurve.pixel_shader );
+ }
+
+ if(this._must_update || !this._curve_texture )
+ this.updateCurve();
+
+ var uniforms = this._uniforms;
+ var curve_texture = this._curve_texture;
+
+ //apply shader
+ temp.drawTo(function() {
+ gl.disable(gl.DEPTH_TEST);
+ tex.bind(0);
+ curve_texture.bind(1);
+ shader.uniforms(uniforms).draw(GL.Mesh.getScreenQuad());
+ });
+
+ this.setOutputData(0, temp);
+ };
+
+ LGraphTextureCurve.prototype.sampleCurve = function(f,points)
+ {
+ var points = points || this._points.RGB;
+ if(!points)
+ return;
+ for(var i = 0; i < points.length - 1; ++i)
+ {
+ var p = points[i];
+ var pn = points[i+1];
+ if(pn[0] < f)
+ continue;
+ var r = (pn[0] - p[0]);
+ if( Math.abs(r) < 0.00001 )
+ return p[1];
+ var local_f = (f - p[0]) / r;
+ return p[1] * (1.0 - local_f) + pn[1] * local_f;
+ }
+ return 0;
+ }
+
+ LGraphTextureCurve.prototype.updateCurve = function()
+ {
+ var values = this._values;
+ var num = values.length / 4;
+ var split = this.properties.split_channels;
+ for(var i = 0; i < num; ++i)
+ {
+ if(split)
+ {
+ values[i*4] = Math.clamp( this.sampleCurve(i/num,this._points.R)*255,0,255);
+ values[i*4+1] = Math.clamp( this.sampleCurve(i/num,this._points.G)*255,0,255);
+ values[i*4+2] = Math.clamp( this.sampleCurve(i/num,this._points.B)*255,0,255);
+ }
+ else
+ {
+ var v = this.sampleCurve(i/num);//sample curve
+ values[i*4] = values[i*4+1] = values[i*4+2] = Math.clamp(v*255,0,255);
+ }
+ values[i*4+3] = 255; //alpha fixed
+ }
+ if(!this._curve_texture)
+ this._curve_texture = new GL.Texture(256,1,{ format: gl.RGBA, magFilter: gl.LINEAR, wrap: gl.CLAMP_TO_EDGE });
+ this._curve_texture.uploadData(values,null,true);
+ }
+
+ LGraphTextureCurve.prototype.onSerialize = function(o)
+ {
+ var curves = {};
+ for(var i in this._points)
+ curves[i] = this._points[i].concat();
+ o.curves = curves;
+ }
+
+ LGraphTextureCurve.prototype.onConfigure = function(o)
+ {
+ this._points = o.curves;
+ if(this.curve_editor)
+ curve_editor.points = this._points;
+ this._must_update = true;
+ }
+
+ LGraphTextureCurve.prototype.onMouseDown = function(e, localpos, graphcanvas)
+ {
+ if(this.curve_editor)
+ {
+ var r = this.curve_editor.onMouseDown([localpos[0],localpos[1]-this.curve_offset], graphcanvas);
+ if(r)
+ this.captureInput(true);
+ return r;
+ }
+ }
+
+ LGraphTextureCurve.prototype.onMouseMove = function(e, localpos, graphcanvas)
+ {
+ if(this.curve_editor)
+ return this.curve_editor.onMouseMove([localpos[0],localpos[1]-this.curve_offset], graphcanvas);
+ }
+
+ LGraphTextureCurve.prototype.onMouseUp = function(e, localpos, graphcanvas)
+ {
+ if(this.curve_editor)
+ return this.curve_editor.onMouseUp([localpos[0],localpos[1]-this.curve_offset], graphcanvas);
+ this.captureInput(false);
+ }
+
+ LGraphTextureCurve.channel_line_colors = { "RGB":"#666","R":"#F33","G":"#3F3","B":"#33F" };
+
+ LGraphTextureCurve.prototype.onDrawBackground = function(ctx, graphcanvas)
+ {
+ if(this.flags.collapsed)
+ return;
+
+ if(!this.curve_editor)
+ this.curve_editor = new LiteGraph.CurveEditor(this._points.R);
+ ctx.save();
+ ctx.translate(0,this.curve_offset);
+ var channel = this.widgets[1].value;
+
+ if(this.properties.split_channels)
+ {
+ if(channel == "RGB")
+ {
+ this.widgets[1].value = channel = "R";
+ this.widgets[1].disabled = false;
+ }
+ this.curve_editor.points = this._points.R;
+ this.curve_editor.draw( ctx, [this.size[0],this.size[1] - this.curve_offset], graphcanvas, "#111", LGraphTextureCurve.channel_line_colors.R, true );
+ ctx.globalCompositeOperation = "lighten";
+ this.curve_editor.points = this._points.G;
+ this.curve_editor.draw( ctx, [this.size[0],this.size[1] - this.curve_offset], graphcanvas, null, LGraphTextureCurve.channel_line_colors.G, true );
+ this.curve_editor.points = this._points.B;
+ this.curve_editor.draw( ctx, [this.size[0],this.size[1] - this.curve_offset], graphcanvas, null, LGraphTextureCurve.channel_line_colors.B, true );
+ ctx.globalCompositeOperation = "source-over";
+ }
+ else
+ {
+ this.widgets[1].value = channel = "RGB";
+ this.widgets[1].disabled = true;
+ }
+
+ this.curve_editor.points = this._points[channel];
+ this.curve_editor.draw( ctx, [this.size[0],this.size[1] - this.curve_offset], graphcanvas, this.properties.split_channels ? null : "#111", LGraphTextureCurve.channel_line_colors[channel] );
+ ctx.restore();
+ }
+
+ LGraphTextureCurve.pixel_shader =
+ "precision highp float;\n\
+ varying vec2 v_coord;\n\
+ uniform sampler2D u_texture;\n\
+ uniform sampler2D u_curve;\n\
+ uniform float u_range;\n\
+ \n\
+ void main() {\n\
+ vec4 color = texture2D( u_texture, v_coord ) * u_range;\n\
+ color.x = texture2D( u_curve, vec2( color.x, 0.5 ) ).x;\n\
+ color.y = texture2D( u_curve, vec2( color.y, 0.5 ) ).y;\n\
+ color.z = texture2D( u_curve, vec2( color.z, 0.5 ) ).z;\n\
+ //color.w = texture2D( u_curve, vec2( color.w, 0.5 ) ).w;\n\
+ gl_FragColor = color;\n\
+ }";
+
+ LiteGraph.registerNodeType("texture/curve", LGraphTextureCurve);
+
//simple exposition, but plan to expand it to support different gamma curves
function LGraphExposition() {
this.addInput("in", "Texture");
@@ -4391,6 +4696,7 @@ void main(void){\n\
//rgb = xyYtoRGB(xyY);\n\
//second\n\
rgb = (rgb / lum) * Ld;\n\
+ rgb = max(rgb,vec3(0.001));\n\
rgb = pow( rgb, vec3( u_igamma ) );\n\
gl_FragColor = vec4( rgb, color.a );\n\
}";
diff --git a/src/nodes/math3d.js b/src/nodes/math3d.js
index 27d139ac5..176588b68 100644
--- a/src/nodes/math3d.js
+++ b/src/nodes/math3d.js
@@ -1,6 +1,69 @@
(function(global) {
var LiteGraph = global.LiteGraph;
+
+ function Math3DMat4()
+ {
+ this.addInput("T", "vec3");
+ this.addInput("R", "vec3");
+ this.addInput("S", "vec3");
+ this.addOutput("mat4", "mat4");
+ this.properties = {
+ "T":[0,0,0],
+ "R":[0,0,0],
+ "S":[1,1,1],
+ R_in_degrees: true
+ };
+ this._result = mat4.create();
+ this._must_update = true;
+ }
+
+ Math3DMat4.title = "mat4";
+ Math3DMat4.temp_quat = new Float32Array([0,0,0,1]);
+ Math3DMat4.temp_mat4 = new Float32Array(16);
+ Math3DMat4.temp_vec3 = new Float32Array(3);
+
+ Math3DMat4.prototype.onPropertyChanged = function(name, value)
+ {
+ this._must_update = true;
+ }
+
+ Math3DMat4.prototype.onExecute = function()
+ {
+ var M = this._result;
+ var Q = Math3DMat4.temp_quat;
+ var temp_mat4 = Math3DMat4.temp_mat4;
+ var temp_vec3 = Math3DMat4.temp_vec3;
+
+ var T = this.getInputData(0);
+ var R = this.getInputData(1);
+ var S = this.getInputData(2);
+
+ if( this._must_update || T || R || S )
+ {
+ T = T || this.properties.T;
+ R = R || this.properties.R;
+ S = S || this.properties.S;
+ mat4.identity( M );
+ mat4.translate( M, M, T );
+ if(this.properties.R_in_degrees)
+ {
+ temp_vec3.set( R );
+ vec3.scale(temp_vec3,temp_vec3,DEG2RAD);
+ quat.fromEuler( Q, temp_vec3 );
+ }
+ else
+ quat.fromEuler( Q, R );
+ mat4.fromQuat( temp_mat4, Q );
+ mat4.multiply( M, M, temp_mat4 );
+ mat4.scale( M, M, S );
+ }
+
+ this.setOutputData(0, M);
+ }
+
+ LiteGraph.registerNodeType("math3d/mat4", Math3DMat4);
+
//Math 3D operation
function Math3DOperation() {
this.addInput("A", "number,vec3");