Name
*
Code
{"properties":{"frame":0,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera1","versions":{"polygonjs":"1.5.14"}},"root":{"type":"root","nodes":{"particles":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"meshBasicBuilder_INSTANCES":{"type":"meshBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"idn"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute2":{"type":"attribute","params":{"name":"idn","texportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.22},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.4000000000000001}},"inputs":[{"index":0,"inputName":"val","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":0.72,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute1","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute2","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":0.76,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"random1","output":"rand"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"raw_input":1,"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"fitFrom01_1","output":"val"},{"index":1,"inputName":"y","node":"fitFrom01_1","output":"val"},{"index":2,"inputName":"z","node":"fitFrom01_1","output":"val"}]},"globals1":{"type":"globals"},"hsvToRgb1":{"type":"hsvToRgb","params":{"hsv":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"hsv","node":"floatToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[null,null,null,null,{"index":4,"inputName":"instanceScale","node":"floatToVec3_2","output":"vec3"}]},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"hsvToRgb1","output":"rgb"}]},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"random2","output":"rand"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]}},"params":{"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":0.8198198198198198,"value":0.5074218750000001},{"position":1,"value":1}]},"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasicBuilder_INSTANCES_PARTICLES":{"type":"meshBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"idn"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute2":{"type":"attribute","params":{"name":"idn","texportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute3":{"type":"attribute","params":{"name":"state"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute3","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.22},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.4000000000000001}},"inputs":[{"index":0,"inputName":"val","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":0.2,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"round1","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute2","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":0.76,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"random1","output":"rand"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"raw_input":1,"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"fitFrom01_1","output":"val"},{"index":1,"inputName":"y","node":"fitFrom01_1","output":"val"},{"index":2,"inputName":"z","node":"fitFrom01_1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"},{"index":1,"inputName":"y","node":"complement1","output":"val"}]},"globals1":{"type":"globals"},"hsvToRgb1":{"type":"hsvToRgb","params":{"hsv":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"hsv","node":"floatToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[null,null,null,null,{"index":4,"inputName":"instanceScale","node":"floatToVec3_2","output":"vec3"}]},"multAdd1":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1000},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"hsvToRgb1","output":"rgb"}]},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"random2","output":"rand"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]},"round1":{"type":"round","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}}},"params":{"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":0.8198198198198198,"value":0.5074218750000001},{"position":1,"value":1}]},"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"pointsParticles":{"type":"pointsBuilder","nodes":{"constant_point_size":{"type":"constant","params":{"float":0.0059000000000000025},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[null,null,null,null,null,{"index":5,"inputName":"gl_PointSize","node":"constant_point_size","output":"val"}]}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-main","type":"PointsMaterial","color":16777215,"size":1,"sizeAttenuation":true,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDistanceMaterial","type":"ShaderMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"diffuse":{"type":"c","value":16777215},"opacity":{"value":1},"map":{"value":null},"mapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaMap":{"value":null},"alphaMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaTest":{"value":0},"displacementMap":{"value":null},"displacementMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"displacementScale":{"value":1},"displacementBias":{"value":0},"size":{"value":1},"scale":{"value":1}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3200},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","fragmentShader":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDepthMaterial","type":"ShaderMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"diffuse":{"type":"c","value":16777215},"opacity":{"value":1},"map":{"value":null},"mapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaMap":{"value":null},"alphaMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaTest":{"value":0},"displacementMap":{"value":null},"displacementMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"displacementScale":{"value":1},"displacementBias":{"value":0},"size":{"value":1},"scale":{"value":1}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","fragmentShader":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDepthDOFMaterial","type":"ShaderMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"size":{"value":1},"scale":{"value":1},"mNear":{"value":0},"mFar":{"value":10}},"defines":{"USE_SIZEATTENUATION":1},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n}\n","fragmentShader":"\nuniform float mNear;\nuniform float mFar;\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\nvoid main() {\n\n\tfloat color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );\n\tgl_FragColor = vec4( vec3( color ), 1.0 );\n\tvec4 diffuseColor = gl_FragColor;\n\n\t// INSERT BODY\n\n\tgl_FragColor.a = diffuseColor.a;\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasic_DEBUG_SPHERE":{"type":"meshBasic"}}},"actor_particles1":{"type":"actor","nodes":{"onScenePause1":{"type":"onScenePause"},"onTick1":{"type":"onTick"},"particlesSystemReset1":{"type":"particlesSystemReset","inputs":[{"index":0,"inputName":"trigger","node":"onScenePause1","output":"trigger"}]},"particlesSystemStepSimulation1":{"type":"particlesSystemStepSimulation","maxInputsCount":2,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"","type":"Texture","isArray":false}]}}},"inputs":["instance1"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["globalsTime","globalsTimeDelta","particlesSystemReset","particlesSystemStepSimulation"],"serializedParamConfigs":[],"eventDatas":[]}},"instance1":{"type":"instance","params":{"attributesToCopy":"instance* id idn restP","material":"../MAT/meshBasicBuilder_INSTANCES"},"inputs":["sphere1","restAttributes1"]},"particlesSystemGpu1":{"type":"particlesSystemGpu","nodes":{"acceleration1":{"type":"acceleration","params":{"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"velocity":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mass":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"force":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"position","node":"null1","output":"val"},{"index":1,"inputName":"velocity","node":"maxLength1","output":"val"}],"connection_points":{"in":[{"name":"position","type":"vec3"},{"name":"velocity","type":"vec3"},{"name":"mass","type":"float"},{"name":"force","type":"vec3"}],"out":[{"name":"position","type":"vec3"},{"name":"velocity","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"attribute_state_IN","output":"val"},{"index":1,"inputName":"add1","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float"},{"name":"add1","type":"float"},{"name":"add2","type":"float"}],"out":[{"name":"sum","type":"float"}]}},"attribute1":{"type":"attribute","params":{"name":"instancePosition","type":2,"texportWhenConnected":1,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"instancePosition","type":2,"texportWhenConnected":1,"exportWhenConnected":true,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":1,"inputs":[{"index":0,"inputName":"in","node":"mix2","output":"mix"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute3":{"type":"attribute","params":{"name":"id","texportWhenConnected":1,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"attribute4":{"type":"attribute","params":{"name":"restP","type":2,"texportWhenConnected":1,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute_state_IN":{"type":"attribute","params":{"name":"state","texportWhenConnected":1,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"attribute_state_OUT":{"type":"attribute","params":{"name":"state","texportWhenConnected":1,"exportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":1,"inputs":[{"index":0,"inputName":"in","node":"clamp1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"clamp1":{"type":"clamp","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"min":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"subtract1","output":"subtract"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"min","type":"float"},{"name":"max","type":"float"}],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"clamp1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"distance1":{"type":"distance","params":{"p0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"p1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"p0","node":"null2","output":"val"},{"index":1,"inputName":"p1","node":"param1","output":"val"}],"connection_points":{"in":[{"name":"p0","type":"vec3"},{"name":"p1","type":"vec3"}],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.04},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.13}},"inputs":[{"index":0,"inputName":"val","node":"random2","output":"rand"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":3.8,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":3.92,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"}]},"globals1":{"type":"globals"},"maxLength1":{"type":"maxLength","params":{"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":4}},"inputs":[{"index":0,"inputName":"val","node":"mix1","output":"mix"}],"connection_points":{"in":[{"name":"val","type":"vec3"},{"name":"max","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"inputs":[{"index":0,"inputName":"value0","node":"multScalar1","output":"val"},{"index":1,"inputName":"value1","node":"param2","output":"val"},{"index":2,"inputName":"blend","node":"mult1","output":"product"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"mix2":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":0.04}},"inputs":[{"index":0,"inputName":"value0","node":"acceleration1","output":"position"},{"index":1,"inputName":"value1","node":"attribute4","output":"val"},{"index":2,"inputName":"blend","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"mult1":{"type":"mult","params":{"mult0":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"mult0","node":"ramp1","output":"val"},{"index":1,"inputName":"mult1","node":"random1","output":"rand"}],"connection_points":{"in":[{"name":"mult0","type":"float"},{"name":"mult1","type":"float"},{"name":"mult2","type":"float"}],"out":[{"name":"product","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.06},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"complement1","output":"val"},{"index":1,"inputName":"preAdd","node":"fitFrom01_1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.9}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"velocity"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"output1":{"type":"output","inputs":[null,{"index":1,"inputName":"velocity","node":"acceleration1","output":"velocity"}]},"param1":{"type":"param","params":{"name":"cursor","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"param2":{"type":"param","params":{"name":"velocity","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"distance1","output":"val"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]},"subtract1":{"type":"subtract","params":{"sub0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"sub1":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.01}},"inputs":[{"index":0,"inputName":"sub0","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"sub0","type":"float"},{"name":"sub1","type":"float"}],"out":[{"name":"subtract","type":"float"}]}}},"params":{"material":"../MAT/meshBasicBuilder_INSTANCES_PARTICLES","cursor":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[0.42964620432324147,1.7448169699853433,0],"overriden_options":{"callback":"{}"}},"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":1},{"position":0.4619883040935673,"value":0}]},"overriden_options":{"callback":"{}"}},"velocity":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[-8.322365384712489,2.385369943426686,0],"overriden_options":{"callback":"{}"}}},"inputs":["actor_particles1"],"persisted_config":{"texture_allocations":{"writable":[{"instancePosition_x_state":[{"name":"instancePosition","size":3,"nodes":["/particles/particlesSystemGpu1/attribute2","/particles/particlesSystemGpu1/attribute1"]},{"name":"state","size":1,"nodes":["/particles/particlesSystemGpu1/attribute_state_OUT","/particles/particlesSystemGpu1/attribute_state_IN"]}]},{"velocity":[{"name":"velocity","size":3,"nodes":["/particles/particlesSystemGpu1/output1"]}]}],"readonly":[{"restP_x_id":[{"name":"restP","size":3,"nodes":["/particles/particlesSystemGpu1/attribute4"]},{"name":"id","size":1,"nodes":["/particles/particlesSystemGpu1/attribute3"]}]}]},"param_uniform_pairs":[["cursor","v_POLY_param_cursor"],["velocity","v_POLY_param_velocity"],["ramp1","v_POLY_ramp_ramp1"]],"uniforms_owner":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/particlesSystemGpu1-main","type":"ShaderMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"v_POLY_param_cursor":{"type":"v3","value":[0.42964620432324147,1.7448169699853433,0]},"v_POLY_param_velocity":{"type":"v3","value":[-8.322365384712489,2.385369943426686,0]},"v_POLY_ramp_ramp1":{"value":null}},"vertexShader":"void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}","fragmentShader":"void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}","lights":false,"clipping":false}}},"point1":{"type":"point","params":{"updateZ":true,"z":"@P.z + 0.2*rand(@id)"},"inputs":["scatter1"]},"restAttributes1":{"type":"restAttributes","params":{"tnormal":false},"inputs":["point1"]},"scatter1":{"type":"scatter","params":{"pointsCount":1200},"inputs":["text1"]},"sphere1":{"type":"sphere","params":{"radius":0.03}},"text1":{"type":"text","params":{"type":1,"justifyMode":2}},"circle1":{"type":"circle","params":{"radius":1.8,"direction":[0,0,1]}},"curveFromPoints1":{"type":"curveFromPoints","params":{"pointsCount":38,"closed":1},"inputs":["circle1"]},"objectProperties1":{"type":"objectProperties","params":{"tname":1,"name":"curve"},"inputs":["curveFromPoints1"]},"merge1":{"type":"merge","inputs":["actor1","objectProperties1","objectProperties2"],"flags":{"display":true}},"circle2":{"type":"circle","params":{"radius":0.31,"segments":20,"direction":[0,0,1]}},"objectProperties2":{"type":"objectProperties","params":{"tname":true,"name":"debugObject"},"inputs":["circle2"]},"actor_OLD":{"type":"actor","nodes":{"divide2":{"type":"divide","params":{"div0":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"div1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"div2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[null,{"index":1,"inputName":"div1","node":"onTick1","output":"delta"}],"connection_points":{"in":[{"name":"div0","type":"float","isArray":false},{"name":"div1","type":"float","isArray":false},{"name":"div2","type":"float","isArray":false}],"out":[{"name":"divide","type":"float","isArray":false}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value","node":"subtract2","output":"sub"},{"index":1,"inputName":"mult","node":"divide2","output":"divide"}],"connection_points":{"in":[{"name":"value","type":"Vector3","isArray":false},{"name":"mult","type":"float","isArray":false}],"out":[{"name":"val","type":"Vector3","isArray":false}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"rayIntersectPlane1","output":"position"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"onTick1":{"type":"onTick"},"plane1":{"type":"plane","params":{"normal":[0,0,1]}},"previousValue1":{"type":"previousValue","params":{"current":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"offset":{"type":"integer","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":2,"inputs":[{"index":0,"inputName":"current","node":"rayIntersectPlane1","output":"position"}],"connection_points":{"in":[{"name":"current","type":"Vector3","isArray":false},{"name":"offset","type":"int","isArray":false}],"out":[{"name":"prev","type":"Vector3","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectPlane1":{"type":"rayIntersectPlane","inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"},{"index":1,"inputName":"Plane","node":"plane1","output":"Plane"}]},"setParam1":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/cursor","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"setParam2","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"null1","output":"out"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"setParam2":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/velocity","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"multScalar1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"subtract2":{"type":"subtract","params":{"sub0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"sub0","node":"rayIntersectPlane1","output":"position"},{"index":1,"inputName":"sub1","node":"previousValue1","output":"prev"}],"connection_points":{"in":[{"name":"sub0","type":"Vector3","isArray":false},{"name":"sub1","type":"Vector3","isArray":false},{"name":"sub2","type":"Vector3","isArray":false}],"out":[{"name":"sub","type":"Vector3","isArray":false}]}}},"inputs":["particlesSystemGpu1"],"persisted_config":{"variableNames":["VAR__plane1_normal","VAR__plane1__1","VAR__rayIntersectPlane1_","VAR__previousValue1_current","VAR__null1_in","VAR__subtract2_sub0","VAR__subtract2_sub1","VAR__subtract2_sub2","VAR__multScalar1_value","VAR__multScalar1__1","VAR__setParam2_val","VAR__setParam1_val"],"variables":[{"type":"Vector3","data":[0,0,0]},{"type":"Plane","data":{"normal":[1,0,0],"constant":0}},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]}],"functionNames":["globalsRayFromCursor","planeSet","globalsTime","globalsTimeDelta","rayIntersectPlane","divideNumber","previousValueVector3","subtractVector","multScalarVector3","getParam","setParamVector3"],"serializedParamConfigs":[],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}},"actor1":{"type":"actor","nodes":{"divide2":{"type":"divide","params":{"div0":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"div1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"div2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[null,{"index":1,"inputName":"div1","node":"onTick1","output":"delta"}],"connection_points":{"in":[{"name":"div0","type":"float","isArray":false},{"name":"div1","type":"float","isArray":false},{"name":"div2","type":"float","isArray":false}],"out":[{"name":"divide","type":"float","isArray":false}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value","node":"subtract2","output":"sub"},{"index":1,"inputName":"mult","node":"divide2","output":"divide"}],"connection_points":{"in":[{"name":"value","type":"Vector3","isArray":false},{"name":"mult","type":"float","isArray":false}],"out":[{"name":"val","type":"Vector3","isArray":false}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"null2","output":"out"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"onTick1":{"type":"onTick"},"plane1":{"type":"plane","params":{"normal":[0,0,1]}},"previousValue1":{"type":"previousValue","params":{"current":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"offset":{"type":"integer","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":2,"inputs":[{"index":0,"inputName":"current","node":"null2","output":"out"}],"connection_points":{"in":[{"name":"current","type":"Vector3","isArray":false},{"name":"offset","type":"int","isArray":false}],"out":[{"name":"prev","type":"Vector3","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectPlane1":{"type":"rayIntersectPlane","inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"},{"index":1,"inputName":"Plane","node":"plane1","output":"Plane"}]},"setParam1":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/cursor","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"setParam2","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"null3","output":"out"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"setParam2":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/velocity","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"multScalar1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"subtract2":{"type":"subtract","params":{"sub0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"sub0","node":"null2","output":"out"},{"index":1,"inputName":"sub1","node":"previousValue1","output":"prev"}],"connection_points":{"in":[{"name":"sub0","type":"Vector3","isArray":false},{"name":"sub1","type":"Vector3","isArray":false},{"name":"sub2","type":"Vector3","isArray":false}],"out":[{"name":"sub","type":"Vector3","isArray":false}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"mix1","output":"mix"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"param1":{"type":"param","params":{"name":"useCursor"},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"catmullRomCurve3GetPoint1","output":"position"},{"index":1,"inputName":"value1","node":"rayIntersectPlane1","output":"position"},{"index":2,"inputName":"blend","node":"param1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"Vector3","isArray":false},{"name":"value1","type":"Vector3","isArray":false},{"name":"blend","type":"float","isArray":false}],"out":[{"name":"mix","type":"Vector3","isArray":false}]}},"getObject1":{"type":"getObject","params":{"getCurrentObject":0,"mask":"*/curve"},"maxInputsCount":2},"getObjectUserData1":{"type":"getObjectUserData","params":{"type":6,"name":"path"},"inputs":[{"index":0,"inputName":"Object3D","node":"getObject1","output":"Object3D"}],"connection_points":{"in":[{"name":"Object3D","type":"Object3D","isArray":false}],"out":[{"name":"val","type":"CatmullRomCurve3","isArray":false}]}},"catmullRomCurve3GetPoint1":{"type":"catmullRomCurve3GetPoint","params":{"t":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"CatmullRomCurve3","node":"getObjectUserData1","output":"val"},{"index":1,"inputName":"t","node":"mod1","output":"mod"}]},"onTick2":{"type":"onTick"},"multAdd1":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":0.25},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"onTick2","output":"time"}],"connection_points":{"in":[{"name":"value","type":"float","isArray":false},{"name":"preAdd","type":"float","isArray":false},{"name":"mult","type":"float","isArray":false},{"name":"postAdd","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"mod1":{"type":"mod","params":{"value0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"value1":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"float","isArray":false},{"name":"value1","type":"float","isArray":false}],"out":[{"name":"mod","type":"float","isArray":false}]}},"setObjectPosition1":{"type":"setObjectPosition","params":{"position":{"overriden_options":{}},"lerp":{"overriden_options":{}},"updateMatrix":{"overriden_options":{}}},"maxInputsCount":5,"inputs":[{"index":0,"inputName":"trigger","node":"setParam1","output":"trigger"},{"index":1,"inputName":"Object3D","node":"getObject2","output":"Object3D"},{"index":2,"inputName":"position","node":"null3","output":"out"}]},"getObject2":{"type":"getObject","params":{"getCurrentObject":0,"mask":"*/debugObject"},"maxInputsCount":2},"null3":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"null1","output":"out"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}}},"params":{"useCursor":{"type":"float","default_value":false,"options":{"spare":true,"computeOnDirty":true,"cook":false},"overriden_options":{"callback":"{}"}}},"inputs":["particlesSystemGpu1"],"persisted_config":{"variableNames":["VAR__plane1_normal","VAR__plane1__1","VAR__rayIntersectPlane1_","VAR__catmullRomCurve3GetPoint1_","VAR__mix1_","VAR__mix1_value0","VAR__mix1_value1","VAR__null2_in","VAR__previousValue1_current","VAR__null1_in","VAR__subtract2_sub0","VAR__subtract2_sub1","VAR__subtract2_sub2","VAR__null3_in","VAR__multScalar1_value","VAR__multScalar1__1","VAR__setParam2_val","VAR__setParam1_val","VAR__setObjectPosition1_position"],"variables":[{"type":"Vector3","data":[0,0,0]},{"type":"Plane","data":{"normal":[1,0,0],"constant":0}},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]}],"functionNames":["getObject","globalsTime","globalsTimeDelta","globalsRayFromCursor","planeSet","getActorNodeParamValue","getObjectUserData","multAdd","mathFloat_4","rayIntersectPlane","divideNumber","mod","mathFloat_2","catmullRomCurve3GetPoint","mix","mathVector3_3vvf","previousValueVector3","subtractVector","multScalarVector3","getParam","setParamVector3","setObjectPosition"],"serializedParamConfigs":[{"type":"float","name":"useCursor","defaultValue":0,"uniformName":"v_POLY_param1_val"}],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}},"cameras":{"type":"geo","nodes":{"cameraControls1":{"type":"cameraControls","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[0.07555345425764966,0.22867827201292842,0.005288156075722042]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera1"],"flags":{"display":true}},"perspectiveCamera1":{"type":"perspectiveCamera","params":{"position":[0,0,7.1]}}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}}},"params":{"bgColor":[0,0,0],"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera1"}},"ui":{"nodes":{"particles":{"pos":[-50,-300],"nodes":{"MAT":{"pos":[-650,700],"nodes":{"meshBasicBuilder_INSTANCES":{"pos":[0,0],"selection":["attribute2","fitFrom01_1","floatToVec2_2","floatToVec3_2","ramp1","random2"],"nodes":{"attribute1":{"pos":[-500,300]},"attribute2":{"pos":[-750,50]},"fitFrom01_1":{"pos":[-300,50]},"floatToVec2_1":{"pos":[-350,300]},"floatToVec2_2":{"pos":[-600,50]},"floatToVec3_1":{"pos":[-150,300]},"floatToVec3_2":{"pos":[-150,50]},"globals1":{"pos":[-850,-150]},"hsvToRgb1":{"pos":[-50,300]},"instanceTransform1":{"pos":[50,0]},"output1":{"pos":[200,0]},"ramp1":{"pos":[-400,50]},"random1":{"pos":[-250,300]},"random2":{"pos":[-500,50]}}},"meshBasicBuilder_INSTANCES_PARTICLES":{"pos":[0,100],"nodes":{"attribute1":{"pos":[-800,300]},"attribute2":{"pos":[-750,50]},"attribute3":{"pos":[-500,600]},"complement1":{"pos":[-350,700]},"fitFrom01_1":{"pos":[-300,50]},"floatToVec2_1":{"pos":[-350,300]},"floatToVec2_2":{"pos":[-600,50]},"floatToVec3_1":{"pos":[-150,300]},"floatToVec3_2":{"pos":[-150,50]},"floatToVec3_3":{"pos":[-200,600]},"globals1":{"pos":[-850,-150]},"hsvToRgb1":{"pos":[-50,300]},"instanceTransform1":{"pos":[50,0]},"multAdd1":{"pos":[-650,300]},"output1":{"pos":[200,0]},"ramp1":{"pos":[-400,50]},"random1":{"pos":[-250,300]},"random2":{"pos":[-500,50]},"round1":{"pos":[-500,300]}}},"pointsParticles":{"pos":[0,-100],"nodes":{"constant_point_size":{"pos":[0,200]},"globals1":{"pos":[-200,0]},"output1":{"pos":[200,0]}}},"meshBasic_DEBUG_SPHERE":{"pos":[0,300]}}},"actor_particles1":{"pos":[-450,850],"nodes":{"onScenePause1":{"pos":[-100,-100]},"onTick1":{"pos":[-100,100]},"particlesSystemReset1":{"pos":[100,-100]},"particlesSystemStepSimulation1":{"pos":[100,100]}}},"instance1":{"pos":[-450,700]},"particlesSystemGpu1":{"pos":[-450,1000],"nodes":{"acceleration1":{"pos":[450,-650]},"add2":{"pos":[150,500]},"attribute1":{"pos":[-600,-800]},"attribute2":{"pos":[800,-550]},"attribute3":{"pos":[-500,200]},"attribute4":{"pos":[450,-350]},"attribute_state_IN":{"pos":[-100,600]},"attribute_state_OUT":{"pos":[700,600]},"clamp1":{"pos":[500,500]},"complement1":{"pos":[550,100]},"distance1":{"pos":[-250,-100]},"fitFrom01_1":{"pos":[-150,350]},"floatToVec2_1":{"pos":[-350,200]},"floatToVec2_2":{"pos":[-350,350]},"globals1":{"pos":[-300,-650]},"maxLength1":{"pos":[250,-550]},"mix1":{"pos":[100,-550]},"mix2":{"pos":[650,-450]},"mult1":{"pos":[0,0]},"multAdd2":{"pos":[700,100]},"multScalar1":{"pos":[-150,-650]},"null1":{"pos":[200,-800]},"null2":{"pos":[-500,-200]},"output1":{"pos":[700,-800]},"param1":{"pos":[-400,50]},"param2":{"pos":[-300,-450]},"ramp1":{"pos":[-150,-100]},"random1":{"pos":[-250,200]},"random2":{"pos":[-250,350]},"subtract1":{"pos":[350,500]}}},"point1":{"pos":[-250,250]},"restAttributes1":{"pos":[-250,400]},"scatter1":{"pos":[-250,0]},"sphere1":{"pos":[-550,500]},"text1":{"pos":[-250,-150]},"circle1":{"pos":[-50,800]},"curveFromPoints1":{"pos":[-50,1000]},"objectProperties1":{"pos":[-50,1150],"comment":"here we use:\\n\\n- `curveFromPoints`: which creates a line object from points, which is just visual, but it also gets assigned a mathematical curve, which we can use in the actor node.\\n\\n- `objectProperties`, which sets the name of the object to `curve`, which will allow use to fetch it from the [actor node](../actor1)"},"merge1":{"pos":[-200,1600],"comment":"here we ensure that we have the 3 objects above in the scene."},"circle2":{"pos":[300,800]},"objectProperties2":{"pos":[300,1150],"comment":"this is just a debug object to better see where the point that affects the particles is. If you remove it, make sure to also unplug the last [setObjectPosition](../actor1/setObjectPosition1) in the actor node."},"actor_OLD":{"pos":[-850,1150],"comment":"this actor node is the one from the particles example","nodes":{"divide2":{"pos":[-150,100]},"multScalar1":{"pos":[50,100]},"null1":{"pos":[-200,600]},"onTick1":{"pos":[-350,0]},"plane1":{"pos":[-600,400]},"previousValue1":{"pos":[-200,400]},"rayFromCursor1":{"pos":[-600,200]},"rayIntersectPlane1":{"pos":[-400,300]},"setParam1":{"pos":[600,0]},"setParam2":{"pos":[250,0]},"subtract2":{"pos":[-50,250]}}},"actor1":{"pos":[-450,1150],"comment":"this actor node is a modified version of the one of the particles example.\\n\\nIt has a parameter `useCursor`, which you can set to either use the curve when at `0`, or to use the cursor when at `1`.\\n\\n[Dive inside](.) to see how it is made.","nodes":{"divide2":{"pos":[-150,100]},"multScalar1":{"pos":[50,100]},"null1":{"pos":[-200,600]},"onTick1":{"pos":[-350,0]},"plane1":{"pos":[-1150,650]},"previousValue1":{"pos":[-200,400]},"rayFromCursor1":{"pos":[-1150,450]},"rayIntersectPlane1":{"pos":[-950,550]},"setParam1":{"pos":[800,0]},"setParam2":{"pos":[250,0]},"subtract2":{"pos":[-50,250]},"null2":{"pos":[-400,250]},"param1":{"pos":[-700,550],"comment":"the value here is set by the parameter `useCursor` on the parent node "},"mix1":{"pos":[-550,250],"comment":"here we switch the input value from the curve point or the cursor"},"getObject1":{"pos":[-1550,-150],"comment":"here we fetch the object `curve` that is set in the nodes above."},"getObjectUserData1":{"pos":[-1200,-150],"comment":"this node is the trickiest one in this setup, as it is not documented. It basically import custom data from the input object. That custom data is referred using the name `path`, and is the mathematical curve created by the [curveFromPoints node](../../curveFromPoints1)."},"catmullRomCurve3GetPoint1":{"pos":[-850,50],"comment":"this node allows us to read a position on a curve, using a parameter from 0 to 1. We use the time to set this parameter value."},"onTick2":{"pos":[-1500,250]},"multAdd1":{"pos":[-1350,250]},"mod1":{"pos":[-1200,250]},"setObjectPosition1":{"pos":[1250,0]},"getObject2":{"pos":[950,300]},"null3":{"pos":[650,200]}}}}},"cameras":{"pos":[-50,-100],"nodes":{"cameraControls1":{"pos":[0,150],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"perspectiveCamera1":{"pos":[0,-50]}}}}},"shaders":{"/particles/MAT/meshBasicBuilder_INSTANCES":{"vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"},"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES":{"vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"},"/particles/MAT/pointsParticles":{"vertex":"uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n// removed:\n//\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}","customDistanceMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDepthMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDepthDOFMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n}\n","customDepthDOFMaterial.fragment":"\nuniform float mNear;\nuniform float mFar;\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\nvoid main() {\n\n\tfloat color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );\n\tgl_FragColor = vec4( vec3( color ), 1.0 );\n\tvec4 diffuseColor = gl_FragColor;\n\n\t// INSERT BODY\n\n\tgl_FragColor.a = diffuseColor.a;\n}\n"},"/particles/particlesSystemGpu1":{"instancePosition_x_state":"#include <common>\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /particles/particlesSystemGpu1/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/particlesSystemGpu1/maxLength1\n//\n//\n// CLAMP_LENGTH\n//\n//\nfloat maxLength(float val, float max_l){\n\treturn min(val, max_l);\n}\nvec2 maxLength(vec2 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec3 maxLength(vec3 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec4 maxLength(vec4 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\n\n\n// /particles/particlesSystemGpu1/acceleration1\nfloat velFromAccel(float vel, float force, float mass, float time_delta){\n\tfloat impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec2 velFromAccel(vec2 vel, vec2 force, float mass, float time_delta){\n\tvec2 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec3 velFromAccel(vec3 vel, vec3 force, float mass, float time_delta){\n\tvec3 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec4 velFromAccel(vec4 vel, vec4 force, float mass, float time_delta){\n\tvec4 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nfloat posFromVel(float position, float velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec2 posFromVel(vec2 position, vec2 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec3 posFromVel(vec3 position, vec3 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec4 posFromVel(vec4 position, vec4 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\n\n// /particles/particlesSystemGpu1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /particles/particlesSystemGpu1/attribute1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/particlesSystemGpu1/globals1\nuniform sampler2D texture_velocity;\n\n// /particles/particlesSystemGpu1/param2\nuniform vec3 v_POLY_param_velocity;\n\n// /particles/particlesSystemGpu1/param1\nuniform vec3 v_POLY_param_cursor;\n\n// /particles/particlesSystemGpu1/attribute3\nuniform sampler2D texture_restP_x_id;\n\n// /particles/particlesSystemGpu1/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/particlesSystemGpu1/acceleration1\nuniform float delta_time;\n\n\n\n\n\nvoid main() {\n\n\tvec2 particleUv = (gl_FragCoord.xy / resolution.xy);\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /particles/particlesSystemGpu1/attribute1\n\tvec3 v_POLY_attribute1_val = texture2D( texture_instancePosition_x_state, particleUv ).xyz;\n\tgl_FragColor.xyz = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/globals1\n\tvec3 v_POLY_globals1_velocity = texture2D( texture_velocity, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/param2\n\tvec3 v_POLY_param2_val = v_POLY_param_velocity;\n\t\n\t// /particles/particlesSystemGpu1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /particles/particlesSystemGpu1/attribute3\n\tfloat v_POLY_attribute3_val = texture2D( texture_restP_x_id, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/attribute4\n\tvec3 v_POLY_attribute4_val = texture2D( texture_restP_x_id, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_IN\n\tfloat v_POLY_attribute_state_IN_val = texture2D( texture_instancePosition_x_state, particleUv ).w;\n\tgl_FragColor.w = v_POLY_attribute_state_IN_val;\n\t\n\t// /particles/particlesSystemGpu1/null1\n\tvec3 v_POLY_null1_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/null2\n\tvec3 v_POLY_null2_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.9*v_POLY_globals1_velocity);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute3_val, 3.8);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute3_val, 3.92);\n\t\n\t// /particles/particlesSystemGpu1/distance1\n\tfloat v_POLY_distance1_val = distance(v_POLY_null2_val, v_POLY_param1_val);\n\t\n\t// /particles/particlesSystemGpu1/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/particlesSystemGpu1/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/particlesSystemGpu1/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_distance1_val, 0.0)).x;\n\t\n\t// /particles/particlesSystemGpu1/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_random2_rand, 0.04, 0.13);\n\t\n\t// /particles/particlesSystemGpu1/mult1\n\tfloat v_POLY_mult1_product = (v_POLY_ramp1_val * v_POLY_random1_rand * 1.0);\n\t\n\t// /particles/particlesSystemGpu1/add2\n\tfloat v_POLY_add2_sum = (v_POLY_attribute_state_IN_val + v_POLY_ramp1_val + 0.0);\n\t\n\t// /particles/particlesSystemGpu1/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_multScalar1_val, v_POLY_param2_val, v_POLY_mult1_product);\n\t\n\t// /particles/particlesSystemGpu1/subtract1\n\tfloat v_POLY_subtract1_subtract = (v_POLY_add2_sum - 0.01);\n\t\n\t// /particles/particlesSystemGpu1/maxLength1\n\tvec3 v_POLY_maxLength1_val = maxLength(v_POLY_mix1_mix, 4.0);\n\t\n\t// /particles/particlesSystemGpu1/clamp1\n\tfloat v_POLY_clamp1_val = clamp(v_POLY_subtract1_subtract, 0.0, 1.0);\n\t\n\t// /particles/particlesSystemGpu1/acceleration1\n\tvec3 v_POLY_acceleration1_velocity = velFromAccel(v_POLY_maxLength1_val, vec3(0.0, 0.0, 0.0), 1.0, delta_time);\n\tvec3 v_POLY_acceleration1_position = posFromVel(v_POLY_null1_val, v_POLY_acceleration1_velocity, delta_time);\n\t\n\t// /particles/particlesSystemGpu1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_clamp1_val);\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_OUT\n\tgl_FragColor.w = v_POLY_clamp1_val;\n\t\n\t// /particles/particlesSystemGpu1/multAdd2\n\tfloat v_POLY_multAdd2_val = (0.06*(v_POLY_complement1_val + v_POLY_fitFrom01_1_val)) + 0.0;\n\t\n\t// /particles/particlesSystemGpu1/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_acceleration1_position, v_POLY_attribute4_val, v_POLY_multAdd2_val);\n\t\n\t// /particles/particlesSystemGpu1/attribute2\n\tgl_FragColor.xyz = v_POLY_mix2_mix;\n\n\n\n\n}","velocity":"#include <common>\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /particles/particlesSystemGpu1/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/particlesSystemGpu1/maxLength1\n//\n//\n// CLAMP_LENGTH\n//\n//\nfloat maxLength(float val, float max_l){\n\treturn min(val, max_l);\n}\nvec2 maxLength(vec2 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec3 maxLength(vec3 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec4 maxLength(vec4 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\n\n\n// /particles/particlesSystemGpu1/acceleration1\nfloat velFromAccel(float vel, float force, float mass, float time_delta){\n\tfloat impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec2 velFromAccel(vec2 vel, vec2 force, float mass, float time_delta){\n\tvec2 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec3 velFromAccel(vec3 vel, vec3 force, float mass, float time_delta){\n\tvec3 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec4 velFromAccel(vec4 vel, vec4 force, float mass, float time_delta){\n\tvec4 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nfloat posFromVel(float position, float velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec2 posFromVel(vec2 position, vec2 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec3 posFromVel(vec3 position, vec3 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec4 posFromVel(vec4 position, vec4 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\n\n// /particles/particlesSystemGpu1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /particles/particlesSystemGpu1/attribute1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/particlesSystemGpu1/globals1\nuniform sampler2D texture_velocity;\n\n// /particles/particlesSystemGpu1/param2\nuniform vec3 v_POLY_param_velocity;\n\n// /particles/particlesSystemGpu1/param1\nuniform vec3 v_POLY_param_cursor;\n\n// /particles/particlesSystemGpu1/attribute3\nuniform sampler2D texture_restP_x_id;\n\n// /particles/particlesSystemGpu1/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/particlesSystemGpu1/acceleration1\nuniform float delta_time;\n\n\n\n\n\nvoid main() {\n\n\tvec2 particleUv = (gl_FragCoord.xy / resolution.xy);\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /particles/particlesSystemGpu1/attribute1\n\tvec3 v_POLY_attribute1_val = texture2D( texture_instancePosition_x_state, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/globals1\n\tvec3 v_POLY_globals1_velocity = texture2D( texture_velocity, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/param2\n\tvec3 v_POLY_param2_val = v_POLY_param_velocity;\n\t\n\t// /particles/particlesSystemGpu1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /particles/particlesSystemGpu1/attribute3\n\tfloat v_POLY_attribute3_val = texture2D( texture_restP_x_id, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/attribute4\n\tvec3 v_POLY_attribute4_val = texture2D( texture_restP_x_id, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_IN\n\tfloat v_POLY_attribute_state_IN_val = texture2D( texture_instancePosition_x_state, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/null1\n\tvec3 v_POLY_null1_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/null2\n\tvec3 v_POLY_null2_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.9*v_POLY_globals1_velocity);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute3_val, 3.8);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute3_val, 3.92);\n\t\n\t// /particles/particlesSystemGpu1/distance1\n\tfloat v_POLY_distance1_val = distance(v_POLY_null2_val, v_POLY_param1_val);\n\t\n\t// /particles/particlesSystemGpu1/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/particlesSystemGpu1/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/particlesSystemGpu1/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_distance1_val, 0.0)).x;\n\t\n\t// /particles/particlesSystemGpu1/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_random2_rand, 0.04, 0.13);\n\t\n\t// /particles/particlesSystemGpu1/mult1\n\tfloat v_POLY_mult1_product = (v_POLY_ramp1_val * v_POLY_random1_rand * 1.0);\n\t\n\t// /particles/particlesSystemGpu1/add2\n\tfloat v_POLY_add2_sum = (v_POLY_attribute_state_IN_val + v_POLY_ramp1_val + 0.0);\n\t\n\t// /particles/particlesSystemGpu1/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_multScalar1_val, v_POLY_param2_val, v_POLY_mult1_product);\n\t\n\t// /particles/particlesSystemGpu1/subtract1\n\tfloat v_POLY_subtract1_subtract = (v_POLY_add2_sum - 0.01);\n\t\n\t// /particles/particlesSystemGpu1/maxLength1\n\tvec3 v_POLY_maxLength1_val = maxLength(v_POLY_mix1_mix, 4.0);\n\t\n\t// /particles/particlesSystemGpu1/clamp1\n\tfloat v_POLY_clamp1_val = clamp(v_POLY_subtract1_subtract, 0.0, 1.0);\n\t\n\t// /particles/particlesSystemGpu1/acceleration1\n\tvec3 v_POLY_acceleration1_velocity = velFromAccel(v_POLY_maxLength1_val, vec3(0.0, 0.0, 0.0), 1.0, delta_time);\n\tvec3 v_POLY_acceleration1_position = posFromVel(v_POLY_null1_val, v_POLY_acceleration1_velocity, delta_time);\n\t\n\t// /particles/particlesSystemGpu1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_clamp1_val);\n\t\n\t// /particles/particlesSystemGpu1/multAdd2\n\tfloat v_POLY_multAdd2_val = (0.06*(v_POLY_complement1_val + v_POLY_fitFrom01_1_val)) + 0.0;\n\t\n\t// /particles/particlesSystemGpu1/output1\n\tgl_FragColor.xyz = v_POLY_acceleration1_velocity;\n\t\n\t// /particles/particlesSystemGpu1/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_acceleration1_position, v_POLY_attribute4_val, v_POLY_multAdd2_val);\n\n\n\n\n}"}},"jsFunctionBodies":{"/particles/actor_particles1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor_particles1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonScenePause() {\n\t\tthis.onScenePause1();\n\t}\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor_particles1/onScenePause1\n\tonScenePause1() {\n\t\tthis.particlesSystemReset1(0);\n\t}\n\n\t// /particles/actor_particles1/onTick1\n\tonTick1() {\n\t\tthis.particlesSystemStepSimulation1(0);\n\t}\n\n\t// /particles/actor_particles1/particlesSystemReset1\n\tparticlesSystemReset1() {\n\t\tparticlesSystemReset(this.object3D);\n\t}\n\n\t// /particles/actor_particles1/particlesSystemStepSimulation1\n\tparticlesSystemStepSimulation1() {\n\t\tparticlesSystemStepSimulation(this.object3D, { texture_: this.v_POLY_particlesSystemStepSimulation1_ });\n\t}\n}\nreturn CustomActorEvaluator;\n","/particles/actor_OLD":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor1/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /particles/actor1/plane1\n\tv_POLY_plane1_Plane = computed(() => planeSet(VAR__plane1_normal.set(0, 0, 1), 0.0, VAR__plane1__1));\n\n\t// /particles/actor1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor1/rayIntersectPlane1\n\tv_POLY_rayIntersectPlane1_position = computed(() =>\n\t\trayIntersectPlane(this.v_POLY_rayFromCursor1_Ray.value, this.v_POLY_plane1_Plane.value, VAR__rayIntersectPlane1_)\n\t);\n\n\t// /particles/actor1/divide2\n\tv_POLY_divide2_divide = computed(() => divideNumber(1.0, this.v_POLY_onTick1_delta.value, 1.0));\n\n\t// /particles/actor1/previousValue1\n\tv_POLY_previousValue1_prev = computed(() =>\n\t\tpreviousValueVector3(\n\t\t\t\"/particles/actor1/previousValue1\",\n\t\t\t1.0,\n\t\t\tVAR__previousValue1_current.copy(this.v_POLY_rayIntersectPlane1_position.value)\n\t\t)\n\t);\n\n\t// /particles/actor1/null1\n\tv_POLY_null1_out = computed(() => VAR__null1_in.copy(this.v_POLY_rayIntersectPlane1_position.value));\n\n\t// /particles/actor1/subtract2\n\tv_POLY_subtract2_sub = computed(() =>\n\t\tsubtractVector(\n\t\t\tVAR__subtract2_sub0.copy(this.v_POLY_rayIntersectPlane1_position.value),\n\t\t\tVAR__subtract2_sub1.copy(this.v_POLY_previousValue1_prev.value),\n\t\t\tVAR__subtract2_sub2.set(0, 0, 0)\n\t\t)\n\t);\n\n\t// /particles/actor1/multScalar1\n\tv_POLY_multScalar1_val = computed(() =>\n\t\tmultScalarVector3(\n\t\t\tVAR__multScalar1_value.copy(this.v_POLY_subtract2_sub.value),\n\t\t\tthis.v_POLY_divide2_divide.value,\n\t\t\tVAR__multScalar1__1\n\t\t)\n\t);\n\n\t// /particles/actor1/setParam2\n\tv_POLY_setParam2_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/velocity\"));\n\n\t// /particles/actor1/setParam1\n\tv_POLY_setParam1_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/cursor\"));\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor1/onTick1\n\tonTick1() {\n\t\tthis.setParam2(0);\n\t}\n\n\t// /particles/actor1/setParam2\n\tsetParam2() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam2_getParamSinceNoInput.value,\n\t\t\tVAR__setParam2_val.copy(this.v_POLY_multScalar1_val.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setParam1(0);\n\t}\n\n\t// /particles/actor1/setParam1\n\tsetParam1() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam1_getParamSinceNoInput.value,\n\t\t\tVAR__setParam1_val.copy(this.v_POLY_null1_out.value),\n\t\t\t1.0\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n","/particles/actor1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor2/getObject1\n\tv_POLY_getObject1_Object3D = computed(() => getObject(this.object3D, false, \"*/curve\"));\n\n\t// /particles/actor2/onTick2\n\tv_POLY_onTick2_time = computed(() => globalsTime());\n\tv_POLY_onTick2_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor2/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /particles/actor2/plane1\n\tv_POLY_plane1_Plane = computed(() => planeSet(VAR__plane1_normal.set(0, 0, 1), 0.0, VAR__plane1__1));\n\n\t// /particles/actor2/param1\n\tv_POLY_param1_val = computed(() => getActorNodeParamValue(\"useCursor\"));\n\n\t// /particles/actor2/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor2/getObjectUserData1\n\tv_POLY_getObjectUserData1_val = computed(() => getObjectUserData(this.v_POLY_getObject1_Object3D.value, \"path\"));\n\n\t// /particles/actor2/multAdd1\n\tv_POLY_multAdd1_val = computed(() => mathFloat_4(multAdd, this.v_POLY_onTick2_time.value, 0.0, 0.25, 0.0));\n\n\t// /particles/actor2/rayIntersectPlane1\n\tv_POLY_rayIntersectPlane1_position = computed(() =>\n\t\trayIntersectPlane(this.v_POLY_rayFromCursor1_Ray.value, this.v_POLY_plane1_Plane.value, VAR__rayIntersectPlane1_)\n\t);\n\n\t// /particles/actor2/divide2\n\tv_POLY_divide2_divide = computed(() => divideNumber(1.0, this.v_POLY_onTick1_delta.value, 1.0));\n\n\t// /particles/actor2/mod1\n\tv_POLY_mod1_mod = computed(() => mathFloat_2(mod, this.v_POLY_multAdd1_val.value, 1.0));\n\n\t// /particles/actor2/catmullRomCurve3GetPoint1\n\tv_POLY_catmullRomCurve3GetPoint1_position = computed(() =>\n\t\tcatmullRomCurve3GetPoint(\n\t\t\tthis.v_POLY_getObjectUserData1_val.value,\n\t\t\tthis.v_POLY_mod1_mod.value,\n\t\t\tVAR__catmullRomCurve3GetPoint1_\n\t\t)\n\t);\n\n\t// /particles/actor2/mix1\n\tv_POLY_mix1_mix = computed(() =>\n\t\tmathVector3_3vvf(\n\t\t\tmix,\n\t\t\tVAR__mix1_value0.copy(this.v_POLY_catmullRomCurve3GetPoint1_position.value),\n\t\t\tVAR__mix1_value1.copy(this.v_POLY_rayIntersectPlane1_position.value),\n\t\t\tthis.v_POLY_param1_val.value,\n\t\t\tVAR__mix1_\n\t\t)\n\t);\n\n\t// /particles/actor2/null2\n\tv_POLY_null2_out = computed(() => VAR__null2_in.copy(this.v_POLY_mix1_mix.value));\n\n\t// /particles/actor2/previousValue1\n\tv_POLY_previousValue1_prev = computed(() =>\n\t\tpreviousValueVector3(\n\t\t\t\"/particles/actor2/previousValue1\",\n\t\t\t1.0,\n\t\t\tVAR__previousValue1_current.copy(this.v_POLY_null2_out.value)\n\t\t)\n\t);\n\n\t// /particles/actor2/null1\n\tv_POLY_null1_out = computed(() => VAR__null1_in.copy(this.v_POLY_null2_out.value));\n\n\t// /particles/actor2/subtract2\n\tv_POLY_subtract2_sub = computed(() =>\n\t\tsubtractVector(\n\t\t\tVAR__subtract2_sub0.copy(this.v_POLY_null2_out.value),\n\t\t\tVAR__subtract2_sub1.copy(this.v_POLY_previousValue1_prev.value),\n\t\t\tVAR__subtract2_sub2.set(0, 0, 0)\n\t\t)\n\t);\n\n\t// /particles/actor2/null3\n\tv_POLY_null3_out = computed(() => VAR__null3_in.copy(this.v_POLY_null1_out.value));\n\n\t// /particles/actor2/multScalar1\n\tv_POLY_multScalar1_val = computed(() =>\n\t\tmultScalarVector3(\n\t\t\tVAR__multScalar1_value.copy(this.v_POLY_subtract2_sub.value),\n\t\t\tthis.v_POLY_divide2_divide.value,\n\t\t\tVAR__multScalar1__1\n\t\t)\n\t);\n\n\t// /particles/actor2/setParam1\n\tv_POLY_setParam1_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/cursor\"));\n\n\t// /particles/actor2/setParam2\n\tv_POLY_setParam2_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/velocity\"));\n\n\t// /particles/actor2/getObject2\n\tv_POLY_getObject2_Object3D = computed(() => getObject(this.object3D, false, \"*/debugObject\"));\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor2/onTick1\n\tonTick1() {\n\t\tthis.setParam2(0);\n\t}\n\n\t// /particles/actor2/setParam2\n\tsetParam2() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam2_getParamSinceNoInput.value,\n\t\t\tVAR__setParam2_val.copy(this.v_POLY_multScalar1_val.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setParam1(0);\n\t}\n\n\t// /particles/actor2/setParam1\n\tsetParam1() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam1_getParamSinceNoInput.value,\n\t\t\tVAR__setParam1_val.copy(this.v_POLY_null3_out.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setObjectPosition1(0);\n\t}\n\n\t// /particles/actor2/setObjectPosition1\n\tsetObjectPosition1() {\n\t\tsetObjectPosition(\n\t\t\tthis.v_POLY_getObject2_Object3D.value,\n\t\t\tVAR__setObjectPosition1_position.copy(this.v_POLY_null3_out.value),\n\t\t\t1.0,\n\t\t\ttrue\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n"}}
Code editor
{"multiple_panel":{"split_ratio":0.66,"split_panel0":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5543217692883486,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/perspectiveCamera1","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false,"initLayoutData":{"camera":{"position":{"x":450,"y":-500},"zoom":1},"history":{"2":{"position":{"x":0,"y":0},"zoom":1},"944":{"position":{"x":450,"y":-500},"zoom":1},"1016":{"position":{"x":0,"y":0},"zoom":1},"1530":{"position":{"x":500,"y":-300},"zoom":1},"2654":{"position":{"x":-250,"y":0},"zoom":1}},"paramsDisplayed":false,"linkIndex":1}}}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":238.81028632912466,"y":-1211.5196831494463},"zoom":0.629222106933593},"history":{"2":{"position":{"x":-76.36752721887316,"y":240.76702702674808},"zoom":1.0222221069335933},"944":{"position":{"x":238.81028632912466,"y":-1211.5196831494463},"zoom":0.629222106933593},"1016":{"position":{"x":-37.84077570371631,"y":18.31005275986273},"zoom":0.8192221069335932},"1530":{"position":{"x":-583.4154199432219,"y":-115.40472383762385},"zoom":0.578222106933593},"2654":{"position":{"x":861.2194050196861,"y":-164.63695462438739},"zoom":0.40222210693359295}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"split_panel1":{"panelTypes":["sceneTree"],"currentPanelIndex":0,"panel_data":{"mask":"*"}},"split_mode":"horizontal"},"currentNodes":["/particles","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor_OLD","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":19,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"createExport":false,"checkRemoteAssetsUse":true,"minimizeFilesCount":false,"compressJs":true,"createZip":false,"runPostExportCommand":false},"paramsModal":[]}
Used nodes
event/cameraOrbitControls;mat/meshBasic;mat/meshBasicBuilder;mat/pointsBuilder;obj/geo;sop/actor;sop/cameraControls;sop/circle;sop/curveFromPoints;sop/instance;sop/materialsNetwork;sop/merge;sop/objectProperties;sop/particlesSystemGpu;sop/perspectiveCamera;sop/point;sop/restAttributes;sop/scatter;sop/sphere;sop/text
Used operations
Used modules
Used assemblers
GL_MESH_BASIC;GL_PARTICLES;GL_POINTS;JS_ACTOR
Used integrations
[]
Used assets
Nodes map
{"/particles":"obj/geo","/particles/MAT":"sop/materialsNetwork","/particles/MAT/meshBasicBuilder_INSTANCES":"mat/meshBasicBuilder","/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES":"mat/meshBasicBuilder","/particles/MAT/pointsParticles":"mat/pointsBuilder","/particles/MAT/meshBasic_DEBUG_SPHERE":"mat/meshBasic","/particles/actor_particles1":"sop/actor","/particles/instance1":"sop/instance","/particles/particlesSystemGpu1":"sop/particlesSystemGpu","/particles/point1":"sop/point","/particles/restAttributes1":"sop/restAttributes","/particles/scatter1":"sop/scatter","/particles/sphere1":"sop/sphere","/particles/text1":"sop/text","/particles/circle1":"sop/circle","/particles/curveFromPoints1":"sop/curveFromPoints","/particles/objectProperties1":"sop/objectProperties","/particles/merge1":"sop/merge","/particles/circle2":"sop/circle","/particles/objectProperties2":"sop/objectProperties","/particles/actor_OLD":"sop/actor","/particles/actor1":"sop/actor","/cameras":"obj/geo","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/perspectiveCamera1":"sop/perspectiveCamera"}
Js version
Editor version
Engine version
Name
*
Code
{"properties":{"frame":0,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera1","versions":{"polygonjs":"1.5.14"}},"root":{"type":"root","nodes":{"particles":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"meshBasicBuilder_INSTANCES":{"type":"meshBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"idn"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute2":{"type":"attribute","params":{"name":"idn","texportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.22},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.4000000000000001}},"inputs":[{"index":0,"inputName":"val","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":0.72,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute1","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute2","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":0.76,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"random1","output":"rand"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"raw_input":1,"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"fitFrom01_1","output":"val"},{"index":1,"inputName":"y","node":"fitFrom01_1","output":"val"},{"index":2,"inputName":"z","node":"fitFrom01_1","output":"val"}]},"globals1":{"type":"globals"},"hsvToRgb1":{"type":"hsvToRgb","params":{"hsv":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"hsv","node":"floatToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[null,null,null,null,{"index":4,"inputName":"instanceScale","node":"floatToVec3_2","output":"vec3"}]},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"hsvToRgb1","output":"rgb"}]},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"random2","output":"rand"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]}},"params":{"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":0.8198198198198198,"value":0.5074218750000001},{"position":1,"value":1}]},"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasicBuilder_INSTANCES_PARTICLES":{"type":"meshBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"idn"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute2":{"type":"attribute","params":{"name":"idn","texportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute3":{"type":"attribute","params":{"name":"state"},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute3","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.22},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.4000000000000001}},"inputs":[{"index":0,"inputName":"val","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":0.2,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"round1","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute2","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":0.76,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"random1","output":"rand"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"raw_input":1,"overriden_options":{}},"y":{"raw_input":1,"overriden_options":{}},"z":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"fitFrom01_1","output":"val"},{"index":1,"inputName":"y","node":"fitFrom01_1","output":"val"},{"index":2,"inputName":"z","node":"fitFrom01_1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"},{"index":1,"inputName":"y","node":"complement1","output":"val"}]},"globals1":{"type":"globals"},"hsvToRgb1":{"type":"hsvToRgb","params":{"hsv":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"hsv","node":"floatToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[null,null,null,null,{"index":4,"inputName":"instanceScale","node":"floatToVec3_2","output":"vec3"}]},"multAdd1":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1000},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"hsvToRgb1","output":"rgb"}]},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"random2","output":"rand"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]},"round1":{"type":"round","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}}},"params":{"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":0.8198198198198198,"value":0.5074218750000001},{"position":1,"value":1}]},"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"ramp","name":"ramp1","defaultValue":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"uniformName":"v_POLY_ramp_ramp1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"pointsParticles":{"type":"pointsBuilder","nodes":{"constant_point_size":{"type":"constant","params":{"float":0.0059000000000000025},"maxInputsCount":0,"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[null,null,null,null,null,{"index":5,"inputName":"gl_PointSize","node":"constant_point_size","output":"val"}]}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-main","type":"PointsMaterial","color":16777215,"size":1,"sizeAttenuation":true,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDistanceMaterial","type":"ShaderMaterial","name":"customDistanceMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"diffuse":{"type":"c","value":16777215},"opacity":{"value":1},"map":{"value":null},"mapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaMap":{"value":null},"alphaMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaTest":{"value":0},"displacementMap":{"value":null},"displacementMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"displacementScale":{"value":1},"displacementBias":{"value":0},"size":{"value":1},"scale":{"value":1}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3200},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","fragmentShader":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDepthMaterial","type":"ShaderMaterial","name":"customDepthMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"diffuse":{"type":"c","value":16777215},"opacity":{"value":1},"map":{"value":null},"mapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaMap":{"value":null},"alphaMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"alphaTest":{"value":0},"displacementMap":{"value":null},"displacementMapTransform":{"type":"m3","value":[1,0,0,0,1,0,0,0,1]},"displacementScale":{"value":1},"displacementBias":{"value":0},"size":{"value":1},"scale":{"value":1}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","fragmentShader":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/MAT/pointsParticles-customDepthDOFMaterial","type":"ShaderMaterial","name":"customDepthDOFMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"size":{"value":1},"scale":{"value":1},"mNear":{"value":0},"mFar":{"value":10}},"defines":{"USE_SIZEATTENUATION":1},"vertexShader":"\nuniform float size;\nuniform float scale;\n#include <common>\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\t#include <project_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n}\n","fragmentShader":"\nuniform float mNear;\nuniform float mFar;\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\nvoid main() {\n\n\tfloat color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );\n\tgl_FragColor = vec4( vec3( color ), 1.0 );\n\tvec4 diffuseColor = gl_FragColor;\n\n\t// INSERT BODY\n\n\tgl_FragColor.a = diffuseColor.a;\n}\n","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasic_DEBUG_SPHERE":{"type":"meshBasic"}}},"actor_particles1":{"type":"actor","nodes":{"onScenePause1":{"type":"onScenePause"},"onTick1":{"type":"onTick"},"particlesSystemReset1":{"type":"particlesSystemReset","inputs":[{"index":0,"inputName":"trigger","node":"onScenePause1","output":"trigger"}]},"particlesSystemStepSimulation1":{"type":"particlesSystemStepSimulation","maxInputsCount":2,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"","type":"Texture","isArray":false}]}}},"inputs":["instance1"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["globalsTime","globalsTimeDelta","particlesSystemReset","particlesSystemStepSimulation"],"serializedParamConfigs":[],"eventDatas":[]}},"instance1":{"type":"instance","params":{"attributesToCopy":"instance* id idn restP","material":"../MAT/meshBasicBuilder_INSTANCES"},"inputs":["sphere1","restAttributes1"]},"particlesSystemGpu1":{"type":"particlesSystemGpu","nodes":{"acceleration1":{"type":"acceleration","params":{"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"velocity":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mass":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"force":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"position","node":"null1","output":"val"},{"index":1,"inputName":"velocity","node":"maxLength1","output":"val"}],"connection_points":{"in":[{"name":"position","type":"vec3"},{"name":"velocity","type":"vec3"},{"name":"mass","type":"float"},{"name":"force","type":"vec3"}],"out":[{"name":"position","type":"vec3"},{"name":"velocity","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"attribute_state_IN","output":"val"},{"index":1,"inputName":"add1","node":"ramp1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float"},{"name":"add1","type":"float"},{"name":"add2","type":"float"}],"out":[{"name":"sum","type":"float"}]}},"attribute1":{"type":"attribute","params":{"name":"instancePosition","type":2,"texportWhenConnected":1,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"instancePosition","type":2,"texportWhenConnected":1,"exportWhenConnected":true,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":1,"inputs":[{"index":0,"inputName":"in","node":"mix2","output":"mix"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute3":{"type":"attribute","params":{"name":"id","texportWhenConnected":1,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"attribute4":{"type":"attribute","params":{"name":"restP","type":2,"texportWhenConnected":1,"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"attribute_state_IN":{"type":"attribute","params":{"name":"state","texportWhenConnected":1,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"attribute_state_OUT":{"type":"attribute","params":{"name":"state","texportWhenConnected":1,"exportWhenConnected":true,"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":1,"inputs":[{"index":0,"inputName":"in","node":"clamp1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"clamp1":{"type":"clamp","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"min":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"subtract1","output":"subtract"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"min","type":"float"},{"name":"max","type":"float"}],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"clamp1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"distance1":{"type":"distance","params":{"p0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"p1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"p0","node":"null2","output":"val"},{"index":1,"inputName":"p1","node":"param1","output":"val"}],"connection_points":{"in":[{"name":"p0","type":"vec3"},{"name":"p1","type":"vec3"}],"out":[{"name":"val","type":"float"}]}},"fitFrom01_1":{"type":"fitFrom01","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"destMin":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.04},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.13}},"inputs":[{"index":0,"inputName":"val","node":"random2","output":"rand"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToVec2_1":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":3.8,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"}]},"floatToVec2_2":{"type":"floatToVec2","params":{"x":{"overriden_options":{}},"y":{"raw_input":3.92,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"attribute3","output":"val"}]},"globals1":{"type":"globals"},"maxLength1":{"type":"maxLength","params":{"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":4}},"inputs":[{"index":0,"inputName":"val","node":"mix1","output":"mix"}],"connection_points":{"in":[{"name":"val","type":"vec3"},{"name":"max","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"inputs":[{"index":0,"inputName":"value0","node":"multScalar1","output":"val"},{"index":1,"inputName":"value1","node":"param2","output":"val"},{"index":2,"inputName":"blend","node":"mult1","output":"product"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"mix2":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":0.04}},"inputs":[{"index":0,"inputName":"value0","node":"acceleration1","output":"position"},{"index":1,"inputName":"value1","node":"attribute4","output":"val"},{"index":2,"inputName":"blend","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"mult1":{"type":"mult","params":{"mult0":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"mult0","node":"ramp1","output":"val"},{"index":1,"inputName":"mult1","node":"random1","output":"rand"}],"connection_points":{"in":[{"name":"mult0","type":"float"},{"name":"mult1","type":"float"},{"name":"mult2","type":"float"}],"out":[{"name":"product","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.06},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"complement1","output":"val"},{"index":1,"inputName":"preAdd","node":"fitFrom01_1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.9}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"velocity"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"output1":{"type":"output","inputs":[null,{"index":1,"inputName":"velocity","node":"acceleration1","output":"velocity"}]},"param1":{"type":"param","params":{"name":"cursor","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"param2":{"type":"param","params":{"name":"velocity","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"ramp1":{"type":"ramp","params":{"input":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"input","node":"distance1","output":"val"}]},"random1":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_1","output":"vec2"}]},"random2":{"type":"random","params":{"seed":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"seed","node":"floatToVec2_2","output":"vec2"}]},"subtract1":{"type":"subtract","params":{"sub0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"sub1":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.01}},"inputs":[{"index":0,"inputName":"sub0","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"sub0","type":"float"},{"name":"sub1","type":"float"}],"out":[{"name":"subtract","type":"float"}]}}},"params":{"material":"../MAT/meshBasicBuilder_INSTANCES_PARTICLES","cursor":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[0.42964620432324147,1.7448169699853433,0],"overriden_options":{"callback":"{}"}},"ramp1":{"type":"ramp","default_value":{"interpolation":"cubic","points":[{"position":0,"value":0},{"position":1,"value":1}]},"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":{"interpolation":"cubic","points":[{"position":0,"value":1},{"position":0.4619883040935673,"value":0}]},"overriden_options":{"callback":"{}"}},"velocity":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[-8.322365384712489,2.385369943426686,0],"overriden_options":{"callback":"{}"}}},"inputs":["actor_particles1"],"persisted_config":{"texture_allocations":{"writable":[{"instancePosition_x_state":[{"name":"instancePosition","size":3,"nodes":["/particles/particlesSystemGpu1/attribute2","/particles/particlesSystemGpu1/attribute1"]},{"name":"state","size":1,"nodes":["/particles/particlesSystemGpu1/attribute_state_OUT","/particles/particlesSystemGpu1/attribute_state_IN"]}]},{"velocity":[{"name":"velocity","size":3,"nodes":["/particles/particlesSystemGpu1/output1"]}]}],"readonly":[{"restP_x_id":[{"name":"restP","size":3,"nodes":["/particles/particlesSystemGpu1/attribute4"]},{"name":"id","size":1,"nodes":["/particles/particlesSystemGpu1/attribute3"]}]}]},"param_uniform_pairs":[["cursor","v_POLY_param_cursor"],["velocity","v_POLY_param_velocity"],["ramp1","v_POLY_ramp_ramp1"]],"uniforms_owner":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/particles/particlesSystemGpu1-main","type":"ShaderMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"forceSinglePass":true,"fog":false,"glslVersion":null,"uniforms":{"v_POLY_param_cursor":{"type":"v3","value":[0.42964620432324147,1.7448169699853433,0]},"v_POLY_param_velocity":{"type":"v3","value":[-8.322365384712489,2.385369943426686,0]},"v_POLY_ramp_ramp1":{"value":null}},"vertexShader":"void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}","fragmentShader":"void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}","lights":false,"clipping":false}}},"point1":{"type":"point","params":{"updateZ":true,"z":"@P.z + 0.2*rand(@id)"},"inputs":["scatter1"]},"restAttributes1":{"type":"restAttributes","params":{"tnormal":false},"inputs":["point1"]},"scatter1":{"type":"scatter","params":{"pointsCount":1200},"inputs":["text1"]},"sphere1":{"type":"sphere","params":{"radius":0.03}},"text1":{"type":"text","params":{"type":1,"justifyMode":2}},"circle1":{"type":"circle","params":{"radius":1.8,"direction":[0,0,1]}},"curveFromPoints1":{"type":"curveFromPoints","params":{"pointsCount":38,"closed":1},"inputs":["circle1"]},"objectProperties1":{"type":"objectProperties","params":{"tname":1,"name":"curve"},"inputs":["curveFromPoints1"]},"merge1":{"type":"merge","inputs":["actor1","objectProperties1","objectProperties2"],"flags":{"display":true}},"circle2":{"type":"circle","params":{"radius":0.31,"segments":20,"direction":[0,0,1]}},"objectProperties2":{"type":"objectProperties","params":{"tname":true,"name":"debugObject"},"inputs":["circle2"]},"actor_OLD":{"type":"actor","nodes":{"divide2":{"type":"divide","params":{"div0":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"div1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"div2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[null,{"index":1,"inputName":"div1","node":"onTick1","output":"delta"}],"connection_points":{"in":[{"name":"div0","type":"float","isArray":false},{"name":"div1","type":"float","isArray":false},{"name":"div2","type":"float","isArray":false}],"out":[{"name":"divide","type":"float","isArray":false}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value","node":"subtract2","output":"sub"},{"index":1,"inputName":"mult","node":"divide2","output":"divide"}],"connection_points":{"in":[{"name":"value","type":"Vector3","isArray":false},{"name":"mult","type":"float","isArray":false}],"out":[{"name":"val","type":"Vector3","isArray":false}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"rayIntersectPlane1","output":"position"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"onTick1":{"type":"onTick"},"plane1":{"type":"plane","params":{"normal":[0,0,1]}},"previousValue1":{"type":"previousValue","params":{"current":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"offset":{"type":"integer","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":2,"inputs":[{"index":0,"inputName":"current","node":"rayIntersectPlane1","output":"position"}],"connection_points":{"in":[{"name":"current","type":"Vector3","isArray":false},{"name":"offset","type":"int","isArray":false}],"out":[{"name":"prev","type":"Vector3","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectPlane1":{"type":"rayIntersectPlane","inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"},{"index":1,"inputName":"Plane","node":"plane1","output":"Plane"}]},"setParam1":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/cursor","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"setParam2","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"null1","output":"out"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"setParam2":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/velocity","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"multScalar1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"subtract2":{"type":"subtract","params":{"sub0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"sub0","node":"rayIntersectPlane1","output":"position"},{"index":1,"inputName":"sub1","node":"previousValue1","output":"prev"}],"connection_points":{"in":[{"name":"sub0","type":"Vector3","isArray":false},{"name":"sub1","type":"Vector3","isArray":false},{"name":"sub2","type":"Vector3","isArray":false}],"out":[{"name":"sub","type":"Vector3","isArray":false}]}}},"inputs":["particlesSystemGpu1"],"persisted_config":{"variableNames":["VAR__plane1_normal","VAR__plane1__1","VAR__rayIntersectPlane1_","VAR__previousValue1_current","VAR__null1_in","VAR__subtract2_sub0","VAR__subtract2_sub1","VAR__subtract2_sub2","VAR__multScalar1_value","VAR__multScalar1__1","VAR__setParam2_val","VAR__setParam1_val"],"variables":[{"type":"Vector3","data":[0,0,0]},{"type":"Plane","data":{"normal":[1,0,0],"constant":0}},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]}],"functionNames":["globalsRayFromCursor","planeSet","globalsTime","globalsTimeDelta","rayIntersectPlane","divideNumber","previousValueVector3","subtractVector","multScalarVector3","getParam","setParamVector3"],"serializedParamConfigs":[],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}},"actor1":{"type":"actor","nodes":{"divide2":{"type":"divide","params":{"div0":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"div1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"div2":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[null,{"index":1,"inputName":"div1","node":"onTick1","output":"delta"}],"connection_points":{"in":[{"name":"div0","type":"float","isArray":false},{"name":"div1","type":"float","isArray":false},{"name":"div2","type":"float","isArray":false}],"out":[{"name":"divide","type":"float","isArray":false}]}},"multScalar1":{"type":"multScalar","params":{"value":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value","node":"subtract2","output":"sub"},{"index":1,"inputName":"mult","node":"divide2","output":"divide"}],"connection_points":{"in":[{"name":"value","type":"Vector3","isArray":false},{"name":"mult","type":"float","isArray":false}],"out":[{"name":"val","type":"Vector3","isArray":false}]}},"null1":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"null2","output":"out"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"onTick1":{"type":"onTick"},"plane1":{"type":"plane","params":{"normal":[0,0,1]}},"previousValue1":{"type":"previousValue","params":{"current":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"offset":{"type":"integer","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":2,"inputs":[{"index":0,"inputName":"current","node":"null2","output":"out"}],"connection_points":{"in":[{"name":"current","type":"Vector3","isArray":false},{"name":"offset","type":"int","isArray":false}],"out":[{"name":"prev","type":"Vector3","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectPlane1":{"type":"rayIntersectPlane","inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"},{"index":1,"inputName":"Plane","node":"plane1","output":"Plane"}]},"setParam1":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/cursor","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"setParam2","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"null3","output":"out"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"setParam2":{"type":"setParam","params":{"type":6,"Param":{"type":"param_path","default_value":"../../particlesSystemGpu1/velocity","options":{"spare":true,"editable":true,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"val","node":"multScalar1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"Vector3","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"subtract2":{"type":"subtract","params":{"sub0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"sub2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"sub0","node":"null2","output":"out"},{"index":1,"inputName":"sub1","node":"previousValue1","output":"prev"}],"connection_points":{"in":[{"name":"sub0","type":"Vector3","isArray":false},{"name":"sub1","type":"Vector3","isArray":false},{"name":"sub2","type":"Vector3","isArray":false}],"out":[{"name":"sub","type":"Vector3","isArray":false}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"mix1","output":"mix"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}},"param1":{"type":"param","params":{"name":"useCursor"},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"catmullRomCurve3GetPoint1","output":"position"},{"index":1,"inputName":"value1","node":"rayIntersectPlane1","output":"position"},{"index":2,"inputName":"blend","node":"param1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"Vector3","isArray":false},{"name":"value1","type":"Vector3","isArray":false},{"name":"blend","type":"float","isArray":false}],"out":[{"name":"mix","type":"Vector3","isArray":false}]}},"getObject1":{"type":"getObject","params":{"getCurrentObject":0,"mask":"*/curve"},"maxInputsCount":2},"getObjectUserData1":{"type":"getObjectUserData","params":{"type":6,"name":"path"},"inputs":[{"index":0,"inputName":"Object3D","node":"getObject1","output":"Object3D"}],"connection_points":{"in":[{"name":"Object3D","type":"Object3D","isArray":false}],"out":[{"name":"val","type":"CatmullRomCurve3","isArray":false}]}},"catmullRomCurve3GetPoint1":{"type":"catmullRomCurve3GetPoint","params":{"t":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"CatmullRomCurve3","node":"getObjectUserData1","output":"val"},{"index":1,"inputName":"t","node":"mod1","output":"mod"}]},"onTick2":{"type":"onTick"},"multAdd1":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":0.25},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"onTick2","output":"time"}],"connection_points":{"in":[{"name":"value","type":"float","isArray":false},{"name":"preAdd","type":"float","isArray":false},{"name":"mult","type":"float","isArray":false},{"name":"postAdd","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"mod1":{"type":"mod","params":{"value0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"value1":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"float","isArray":false},{"name":"value1","type":"float","isArray":false}],"out":[{"name":"mod","type":"float","isArray":false}]}},"setObjectPosition1":{"type":"setObjectPosition","params":{"position":{"overriden_options":{}},"lerp":{"overriden_options":{}},"updateMatrix":{"overriden_options":{}}},"maxInputsCount":5,"inputs":[{"index":0,"inputName":"trigger","node":"setParam1","output":"trigger"},{"index":1,"inputName":"Object3D","node":"getObject2","output":"Object3D"},{"index":2,"inputName":"position","node":"null3","output":"out"}]},"getObject2":{"type":"getObject","params":{"getCurrentObject":0,"mask":"*/debugObject"},"maxInputsCount":2},"null3":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"null1","output":"out"}],"connection_points":{"in":[{"name":"in","type":"Vector3","isArray":false}],"out":[{"name":"out","type":"Vector3","isArray":false}]}}},"params":{"useCursor":{"type":"float","default_value":false,"options":{"spare":true,"computeOnDirty":true,"cook":false},"overriden_options":{"callback":"{}"}}},"inputs":["particlesSystemGpu1"],"persisted_config":{"variableNames":["VAR__plane1_normal","VAR__plane1__1","VAR__rayIntersectPlane1_","VAR__catmullRomCurve3GetPoint1_","VAR__mix1_","VAR__mix1_value0","VAR__mix1_value1","VAR__null2_in","VAR__previousValue1_current","VAR__null1_in","VAR__subtract2_sub0","VAR__subtract2_sub1","VAR__subtract2_sub2","VAR__null3_in","VAR__multScalar1_value","VAR__multScalar1__1","VAR__setParam2_val","VAR__setParam1_val","VAR__setObjectPosition1_position"],"variables":[{"type":"Vector3","data":[0,0,0]},{"type":"Plane","data":{"normal":[1,0,0],"constant":0}},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]},{"type":"Vector3","data":[0,0,0]}],"functionNames":["getObject","globalsTime","globalsTimeDelta","globalsRayFromCursor","planeSet","getActorNodeParamValue","getObjectUserData","multAdd","mathFloat_4","rayIntersectPlane","divideNumber","mod","mathFloat_2","catmullRomCurve3GetPoint","mix","mathVector3_3vvf","previousValueVector3","subtractVector","multScalarVector3","getParam","setParamVector3","setObjectPosition"],"serializedParamConfigs":[{"type":"float","name":"useCursor","defaultValue":0,"uniformName":"v_POLY_param1_val"}],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}},"cameras":{"type":"geo","nodes":{"cameraControls1":{"type":"cameraControls","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[0.07555345425764966,0.22867827201292842,0.005288156075722042]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera1"],"flags":{"display":true}},"perspectiveCamera1":{"type":"perspectiveCamera","params":{"position":[0,0,7.1]}}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}}},"params":{"bgColor":[0,0,0],"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera1"}},"ui":{"nodes":{"particles":{"pos":[-50,-300],"nodes":{"MAT":{"pos":[-650,700],"nodes":{"meshBasicBuilder_INSTANCES":{"pos":[0,0],"selection":["attribute2","fitFrom01_1","floatToVec2_2","floatToVec3_2","ramp1","random2"],"nodes":{"attribute1":{"pos":[-500,300]},"attribute2":{"pos":[-750,50]},"fitFrom01_1":{"pos":[-300,50]},"floatToVec2_1":{"pos":[-350,300]},"floatToVec2_2":{"pos":[-600,50]},"floatToVec3_1":{"pos":[-150,300]},"floatToVec3_2":{"pos":[-150,50]},"globals1":{"pos":[-850,-150]},"hsvToRgb1":{"pos":[-50,300]},"instanceTransform1":{"pos":[50,0]},"output1":{"pos":[200,0]},"ramp1":{"pos":[-400,50]},"random1":{"pos":[-250,300]},"random2":{"pos":[-500,50]}}},"meshBasicBuilder_INSTANCES_PARTICLES":{"pos":[0,100],"nodes":{"attribute1":{"pos":[-800,300]},"attribute2":{"pos":[-750,50]},"attribute3":{"pos":[-500,600]},"complement1":{"pos":[-350,700]},"fitFrom01_1":{"pos":[-300,50]},"floatToVec2_1":{"pos":[-350,300]},"floatToVec2_2":{"pos":[-600,50]},"floatToVec3_1":{"pos":[-150,300]},"floatToVec3_2":{"pos":[-150,50]},"floatToVec3_3":{"pos":[-200,600]},"globals1":{"pos":[-850,-150]},"hsvToRgb1":{"pos":[-50,300]},"instanceTransform1":{"pos":[50,0]},"multAdd1":{"pos":[-650,300]},"output1":{"pos":[200,0]},"ramp1":{"pos":[-400,50]},"random1":{"pos":[-250,300]},"random2":{"pos":[-500,50]},"round1":{"pos":[-500,300]}}},"pointsParticles":{"pos":[0,-100],"nodes":{"constant_point_size":{"pos":[0,200]},"globals1":{"pos":[-200,0]},"output1":{"pos":[200,0]}}},"meshBasic_DEBUG_SPHERE":{"pos":[0,300]}}},"actor_particles1":{"pos":[-450,850],"nodes":{"onScenePause1":{"pos":[-100,-100]},"onTick1":{"pos":[-100,100]},"particlesSystemReset1":{"pos":[100,-100]},"particlesSystemStepSimulation1":{"pos":[100,100]}}},"instance1":{"pos":[-450,700]},"particlesSystemGpu1":{"pos":[-450,1000],"nodes":{"acceleration1":{"pos":[450,-650]},"add2":{"pos":[150,500]},"attribute1":{"pos":[-600,-800]},"attribute2":{"pos":[800,-550]},"attribute3":{"pos":[-500,200]},"attribute4":{"pos":[450,-350]},"attribute_state_IN":{"pos":[-100,600]},"attribute_state_OUT":{"pos":[700,600]},"clamp1":{"pos":[500,500]},"complement1":{"pos":[550,100]},"distance1":{"pos":[-250,-100]},"fitFrom01_1":{"pos":[-150,350]},"floatToVec2_1":{"pos":[-350,200]},"floatToVec2_2":{"pos":[-350,350]},"globals1":{"pos":[-300,-650]},"maxLength1":{"pos":[250,-550]},"mix1":{"pos":[100,-550]},"mix2":{"pos":[650,-450]},"mult1":{"pos":[0,0]},"multAdd2":{"pos":[700,100]},"multScalar1":{"pos":[-150,-650]},"null1":{"pos":[200,-800]},"null2":{"pos":[-500,-200]},"output1":{"pos":[700,-800]},"param1":{"pos":[-400,50]},"param2":{"pos":[-300,-450]},"ramp1":{"pos":[-150,-100]},"random1":{"pos":[-250,200]},"random2":{"pos":[-250,350]},"subtract1":{"pos":[350,500]}}},"point1":{"pos":[-250,250]},"restAttributes1":{"pos":[-250,400]},"scatter1":{"pos":[-250,0]},"sphere1":{"pos":[-550,500]},"text1":{"pos":[-250,-150]},"circle1":{"pos":[-50,800]},"curveFromPoints1":{"pos":[-50,1000]},"objectProperties1":{"pos":[-50,1150],"comment":"here we use:\\n\\n- `curveFromPoints`: which creates a line object from points, which is just visual, but it also gets assigned a mathematical curve, which we can use in the actor node.\\n\\n- `objectProperties`, which sets the name of the object to `curve`, which will allow use to fetch it from the [actor node](../actor1)"},"merge1":{"pos":[-200,1600],"comment":"here we ensure that we have the 3 objects above in the scene."},"circle2":{"pos":[300,800]},"objectProperties2":{"pos":[300,1150],"comment":"this is just a debug object to better see where the point that affects the particles is. If you remove it, make sure to also unplug the last [setObjectPosition](../actor1/setObjectPosition1) in the actor node."},"actor_OLD":{"pos":[-850,1150],"comment":"this actor node is the one from the particles example","nodes":{"divide2":{"pos":[-150,100]},"multScalar1":{"pos":[50,100]},"null1":{"pos":[-200,600]},"onTick1":{"pos":[-350,0]},"plane1":{"pos":[-600,400]},"previousValue1":{"pos":[-200,400]},"rayFromCursor1":{"pos":[-600,200]},"rayIntersectPlane1":{"pos":[-400,300]},"setParam1":{"pos":[600,0]},"setParam2":{"pos":[250,0]},"subtract2":{"pos":[-50,250]}}},"actor1":{"pos":[-450,1150],"comment":"this actor node is a modified version of the one of the particles example.\\n\\nIt has a parameter `useCursor`, which you can set to either use the curve when at `0`, or to use the cursor when at `1`.\\n\\n[Dive inside](.) to see how it is made.","nodes":{"divide2":{"pos":[-150,100]},"multScalar1":{"pos":[50,100]},"null1":{"pos":[-200,600]},"onTick1":{"pos":[-350,0]},"plane1":{"pos":[-1150,650]},"previousValue1":{"pos":[-200,400]},"rayFromCursor1":{"pos":[-1150,450]},"rayIntersectPlane1":{"pos":[-950,550]},"setParam1":{"pos":[800,0]},"setParam2":{"pos":[250,0]},"subtract2":{"pos":[-50,250]},"null2":{"pos":[-400,250]},"param1":{"pos":[-700,550],"comment":"the value here is set by the parameter `useCursor` on the parent node "},"mix1":{"pos":[-550,250],"comment":"here we switch the input value from the curve point or the cursor"},"getObject1":{"pos":[-1550,-150],"comment":"here we fetch the object `curve` that is set in the nodes above."},"getObjectUserData1":{"pos":[-1200,-150],"comment":"this node is the trickiest one in this setup, as it is not documented. It basically import custom data from the input object. That custom data is referred using the name `path`, and is the mathematical curve created by the [curveFromPoints node](../../curveFromPoints1)."},"catmullRomCurve3GetPoint1":{"pos":[-850,50],"comment":"this node allows us to read a position on a curve, using a parameter from 0 to 1. We use the time to set this parameter value."},"onTick2":{"pos":[-1500,250]},"multAdd1":{"pos":[-1350,250]},"mod1":{"pos":[-1200,250]},"setObjectPosition1":{"pos":[1250,0]},"getObject2":{"pos":[950,300]},"null3":{"pos":[650,200]}}}}},"cameras":{"pos":[-50,-100],"nodes":{"cameraControls1":{"pos":[0,150],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"perspectiveCamera1":{"pos":[0,-50]}}}}},"shaders":{"/particles/MAT/meshBasicBuilder_INSTANCES":{"vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_idn;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute1_val, 0.72);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"},"/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES":{"vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\nattribute float idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nattribute vec2 particlesSimUv;\nattribute vec4 instanceQuaternion;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute2\n\tfloat v_POLY_attribute2_val = idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tv_POLY_attribute_idn = float(idn);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute2_val, 0.0);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_random2_rand, 0.0)).x;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_ramp1_val, 0.22, 1.4000000000000001);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\n\tparticlesSimUvVarying = particlesSimUv;\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= v_POLY_floatToVec3_2_vec3;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += texture2D( texture_instancePosition_x_state, particlesSimUvVarying ).xyz;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n// https://github.com/hughsk/glsl-hsv2rgb\n// https://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 hsv2rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\n\n\n\n\n\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\nvarying float v_POLY_attribute_idn;\n\n// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/instanceTransform1\nvarying vec2 particlesSimUvVarying;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_idn;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/multAdd1\n\tfloat v_POLY_multAdd1_val = (1000.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd1_val)*floor(abs(v_POLY_multAdd1_val)+0.5);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_round1_val, 0.2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_random1_rand, 1.0, 0.76);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/hsvToRgb1\n\tvec3 v_POLY_hsvToRgb1_rgb = hsv2rgb(v_POLY_floatToVec3_1_vec3);\n\t\n\t// /particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES/output1\n\tdiffuseColor.xyz = v_POLY_hsvToRgb1_rgb;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"},"/particles/MAT/pointsParticles":{"vertex":"uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include <color_vertex>\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n// removed:\n//\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}","customDistanceMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDepthMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n#include <clipping_planes_pars_vertex>\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDepthDOFMaterial.vertex":"\nuniform float size;\nuniform float scale;\n#include <common>\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /particles/MAT/pointsParticles/constant_point_size\n\tfloat v_POLY_constant_point_size_val = 0.0059000000000000025;\n\t\n\t// /particles/MAT/pointsParticles/output1\n\tvec3 transformed = position;\n\tvec3 objectNormal = normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\tgl_PointSize = v_POLY_constant_point_size_val * size * 10.0;\n\n\n\n\n\n\t#include <project_vertex>\n\n\tvViewZDepth = - mvPosition.z;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\n}\n","customDepthDOFMaterial.fragment":"\nuniform float mNear;\nuniform float mFar;\n\nvarying float vViewZDepth;\n\n// INSERT DEFINES\n\nvoid main() {\n\n\tfloat color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );\n\tgl_FragColor = vec4( vec3( color ), 1.0 );\n\tvec4 diffuseColor = gl_FragColor;\n\n\t// INSERT BODY\n\n\tgl_FragColor.a = diffuseColor.a;\n}\n"},"/particles/particlesSystemGpu1":{"instancePosition_x_state":"#include <common>\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /particles/particlesSystemGpu1/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/particlesSystemGpu1/maxLength1\n//\n//\n// CLAMP_LENGTH\n//\n//\nfloat maxLength(float val, float max_l){\n\treturn min(val, max_l);\n}\nvec2 maxLength(vec2 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec3 maxLength(vec3 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec4 maxLength(vec4 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\n\n\n// /particles/particlesSystemGpu1/acceleration1\nfloat velFromAccel(float vel, float force, float mass, float time_delta){\n\tfloat impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec2 velFromAccel(vec2 vel, vec2 force, float mass, float time_delta){\n\tvec2 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec3 velFromAccel(vec3 vel, vec3 force, float mass, float time_delta){\n\tvec3 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec4 velFromAccel(vec4 vel, vec4 force, float mass, float time_delta){\n\tvec4 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nfloat posFromVel(float position, float velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec2 posFromVel(vec2 position, vec2 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec3 posFromVel(vec3 position, vec3 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec4 posFromVel(vec4 position, vec4 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\n\n// /particles/particlesSystemGpu1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /particles/particlesSystemGpu1/attribute1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/particlesSystemGpu1/globals1\nuniform sampler2D texture_velocity;\n\n// /particles/particlesSystemGpu1/param2\nuniform vec3 v_POLY_param_velocity;\n\n// /particles/particlesSystemGpu1/param1\nuniform vec3 v_POLY_param_cursor;\n\n// /particles/particlesSystemGpu1/attribute3\nuniform sampler2D texture_restP_x_id;\n\n// /particles/particlesSystemGpu1/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/particlesSystemGpu1/acceleration1\nuniform float delta_time;\n\n\n\n\n\nvoid main() {\n\n\tvec2 particleUv = (gl_FragCoord.xy / resolution.xy);\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /particles/particlesSystemGpu1/attribute1\n\tvec3 v_POLY_attribute1_val = texture2D( texture_instancePosition_x_state, particleUv ).xyz;\n\tgl_FragColor.xyz = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/globals1\n\tvec3 v_POLY_globals1_velocity = texture2D( texture_velocity, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/param2\n\tvec3 v_POLY_param2_val = v_POLY_param_velocity;\n\t\n\t// /particles/particlesSystemGpu1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /particles/particlesSystemGpu1/attribute3\n\tfloat v_POLY_attribute3_val = texture2D( texture_restP_x_id, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/attribute4\n\tvec3 v_POLY_attribute4_val = texture2D( texture_restP_x_id, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_IN\n\tfloat v_POLY_attribute_state_IN_val = texture2D( texture_instancePosition_x_state, particleUv ).w;\n\tgl_FragColor.w = v_POLY_attribute_state_IN_val;\n\t\n\t// /particles/particlesSystemGpu1/null1\n\tvec3 v_POLY_null1_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/null2\n\tvec3 v_POLY_null2_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.9*v_POLY_globals1_velocity);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute3_val, 3.8);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute3_val, 3.92);\n\t\n\t// /particles/particlesSystemGpu1/distance1\n\tfloat v_POLY_distance1_val = distance(v_POLY_null2_val, v_POLY_param1_val);\n\t\n\t// /particles/particlesSystemGpu1/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/particlesSystemGpu1/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/particlesSystemGpu1/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_distance1_val, 0.0)).x;\n\t\n\t// /particles/particlesSystemGpu1/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_random2_rand, 0.04, 0.13);\n\t\n\t// /particles/particlesSystemGpu1/mult1\n\tfloat v_POLY_mult1_product = (v_POLY_ramp1_val * v_POLY_random1_rand * 1.0);\n\t\n\t// /particles/particlesSystemGpu1/add2\n\tfloat v_POLY_add2_sum = (v_POLY_attribute_state_IN_val + v_POLY_ramp1_val + 0.0);\n\t\n\t// /particles/particlesSystemGpu1/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_multScalar1_val, v_POLY_param2_val, v_POLY_mult1_product);\n\t\n\t// /particles/particlesSystemGpu1/subtract1\n\tfloat v_POLY_subtract1_subtract = (v_POLY_add2_sum - 0.01);\n\t\n\t// /particles/particlesSystemGpu1/maxLength1\n\tvec3 v_POLY_maxLength1_val = maxLength(v_POLY_mix1_mix, 4.0);\n\t\n\t// /particles/particlesSystemGpu1/clamp1\n\tfloat v_POLY_clamp1_val = clamp(v_POLY_subtract1_subtract, 0.0, 1.0);\n\t\n\t// /particles/particlesSystemGpu1/acceleration1\n\tvec3 v_POLY_acceleration1_velocity = velFromAccel(v_POLY_maxLength1_val, vec3(0.0, 0.0, 0.0), 1.0, delta_time);\n\tvec3 v_POLY_acceleration1_position = posFromVel(v_POLY_null1_val, v_POLY_acceleration1_velocity, delta_time);\n\t\n\t// /particles/particlesSystemGpu1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_clamp1_val);\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_OUT\n\tgl_FragColor.w = v_POLY_clamp1_val;\n\t\n\t// /particles/particlesSystemGpu1/multAdd2\n\tfloat v_POLY_multAdd2_val = (0.06*(v_POLY_complement1_val + v_POLY_fitFrom01_1_val)) + 0.0;\n\t\n\t// /particles/particlesSystemGpu1/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_acceleration1_position, v_POLY_attribute4_val, v_POLY_multAdd2_val);\n\t\n\t// /particles/particlesSystemGpu1/attribute2\n\tgl_FragColor.xyz = v_POLY_mix2_mix;\n\n\n\n\n}","velocity":"#include <common>\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /particles/particlesSystemGpu1/fitFrom01_1\n//\n//\n// FIT\n//\n//\nfloat fit(float val, float srcMin, float srcMax, float destMin, float destMax){\n\tfloat src_range = srcMax - srcMin;\n\tfloat dest_range = destMax - destMin;\n\n\tfloat r = (val - srcMin) / src_range;\n\treturn (r * dest_range) + destMin;\n}\nvec2 fit(vec2 val, vec2 srcMin, vec2 srcMax, vec2 destMin, vec2 destMax){\n\treturn vec2(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y)\n\t);\n}\nvec3 fit(vec3 val, vec3 srcMin, vec3 srcMax, vec3 destMin, vec3 destMax){\n\treturn vec3(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z)\n\t);\n}\nvec4 fit(vec4 val, vec4 srcMin, vec4 srcMax, vec4 destMin, vec4 destMax){\n\treturn vec4(\n\t\tfit(val.x, srcMin.x, srcMax.x, destMin.x, destMax.x),\n\t\tfit(val.y, srcMin.y, srcMax.y, destMin.y, destMax.y),\n\t\tfit(val.z, srcMin.z, srcMax.z, destMin.z, destMax.z),\n\t\tfit(val.w, srcMin.w, srcMax.w, destMin.w, destMax.w)\n\t);\n}\n\n//\n//\n// FIT TO 01\n// fits the range [srcMin, srcMax] to [0, 1]\n//\nfloat fitTo01(float val, float srcMin, float srcMax){\n\tfloat size = srcMax - srcMin;\n\treturn (val - srcMin) / size;\n}\nvec2 fitTo01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitTo01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitTo01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitTo01(val.x, srcMin.x, srcMax.x),\n\t\tfitTo01(val.y, srcMin.y, srcMax.y),\n\t\tfitTo01(val.z, srcMin.z, srcMax.z),\n\t\tfitTo01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01\n// fits the range [0, 1] to [destMin, destMax]\n//\nfloat fitFrom01(float val, float destMin, float destMax){\n\treturn fit(val, 0.0, 1.0, destMin, destMax);\n}\nvec2 fitFrom01(vec2 val, vec2 srcMin, vec2 srcMax){\n\treturn vec2(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y)\n\t);\n}\nvec3 fitFrom01(vec3 val, vec3 srcMin, vec3 srcMax){\n\treturn vec3(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z)\n\t);\n}\nvec4 fitFrom01(vec4 val, vec4 srcMin, vec4 srcMax){\n\treturn vec4(\n\t\tfitFrom01(val.x, srcMin.x, srcMax.x),\n\t\tfitFrom01(val.y, srcMin.y, srcMax.y),\n\t\tfitFrom01(val.z, srcMin.z, srcMax.z),\n\t\tfitFrom01(val.w, srcMin.w, srcMax.w)\n\t);\n}\n\n//\n//\n// FIT FROM 01 TO VARIANCE\n// fits the range [0, 1] to [center - variance, center + variance]\n//\nfloat fitFrom01ToVariance(float val, float center, float variance){\n\treturn fitFrom01(val, center - variance, center + variance);\n}\nvec2 fitFrom01ToVariance(vec2 val, vec2 center, vec2 variance){\n\treturn vec2(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y)\n\t);\n}\nvec3 fitFrom01ToVariance(vec3 val, vec3 center, vec3 variance){\n\treturn vec3(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z)\n\t);\n}\nvec4 fitFrom01ToVariance(vec4 val, vec4 center, vec4 variance){\n\treturn vec4(\n\t\tfitFrom01ToVariance(val.x, center.x, variance.x),\n\t\tfitFrom01ToVariance(val.y, center.y, variance.y),\n\t\tfitFrom01ToVariance(val.z, center.z, variance.z),\n\t\tfitFrom01ToVariance(val.w, center.w, variance.w)\n\t);\n}\n\n// /particles/particlesSystemGpu1/maxLength1\n//\n//\n// CLAMP_LENGTH\n//\n//\nfloat maxLength(float val, float max_l){\n\treturn min(val, max_l);\n}\nvec2 maxLength(vec2 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec3 maxLength(vec3 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\nvec4 maxLength(vec4 val, float max_l){\n\tfloat vec_length = length(val);\n\tif(vec_length == 0.0){\n\t\treturn val;\n\t} else {\n\t\tfloat new_length = min(vec_length, max_l);\n\t\treturn new_length * normalize(val);\n\t}\n}\n\n\n// /particles/particlesSystemGpu1/acceleration1\nfloat velFromAccel(float vel, float force, float mass, float time_delta){\n\tfloat impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec2 velFromAccel(vec2 vel, vec2 force, float mass, float time_delta){\n\tvec2 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec3 velFromAccel(vec3 vel, vec3 force, float mass, float time_delta){\n\tvec3 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nvec4 velFromAccel(vec4 vel, vec4 force, float mass, float time_delta){\n\tvec4 impulse = (time_delta * mass) * force;\n\treturn vel + impulse;\n}\nfloat posFromVel(float position, float velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec2 posFromVel(vec2 position, vec2 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec3 posFromVel(vec3 position, vec3 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\nvec4 posFromVel(vec4 position, vec4 velocity, float time_delta){\n\treturn position + (time_delta * velocity);\n}\n\n// /particles/particlesSystemGpu1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /particles/particlesSystemGpu1/attribute1\nuniform sampler2D texture_instancePosition_x_state;\n\n// /particles/particlesSystemGpu1/globals1\nuniform sampler2D texture_velocity;\n\n// /particles/particlesSystemGpu1/param2\nuniform vec3 v_POLY_param_velocity;\n\n// /particles/particlesSystemGpu1/param1\nuniform vec3 v_POLY_param_cursor;\n\n// /particles/particlesSystemGpu1/attribute3\nuniform sampler2D texture_restP_x_id;\n\n// /particles/particlesSystemGpu1/ramp1\nuniform sampler2D v_POLY_ramp_ramp1;\n\n// /particles/particlesSystemGpu1/acceleration1\nuniform float delta_time;\n\n\n\n\n\nvoid main() {\n\n\tvec2 particleUv = (gl_FragCoord.xy / resolution.xy);\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /particles/particlesSystemGpu1/attribute1\n\tvec3 v_POLY_attribute1_val = texture2D( texture_instancePosition_x_state, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/globals1\n\tvec3 v_POLY_globals1_velocity = texture2D( texture_velocity, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/param2\n\tvec3 v_POLY_param2_val = v_POLY_param_velocity;\n\t\n\t// /particles/particlesSystemGpu1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /particles/particlesSystemGpu1/attribute3\n\tfloat v_POLY_attribute3_val = texture2D( texture_restP_x_id, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/attribute4\n\tvec3 v_POLY_attribute4_val = texture2D( texture_restP_x_id, particleUv ).xyz;\n\t\n\t// /particles/particlesSystemGpu1/attribute_state_IN\n\tfloat v_POLY_attribute_state_IN_val = texture2D( texture_instancePosition_x_state, particleUv ).w;\n\t\n\t// /particles/particlesSystemGpu1/null1\n\tvec3 v_POLY_null1_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/null2\n\tvec3 v_POLY_null2_val = v_POLY_attribute1_val;\n\t\n\t// /particles/particlesSystemGpu1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.9*v_POLY_globals1_velocity);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_1\n\tvec2 v_POLY_floatToVec2_1_vec2 = vec2(v_POLY_attribute3_val, 3.8);\n\t\n\t// /particles/particlesSystemGpu1/floatToVec2_2\n\tvec2 v_POLY_floatToVec2_2_vec2 = vec2(v_POLY_attribute3_val, 3.92);\n\t\n\t// /particles/particlesSystemGpu1/distance1\n\tfloat v_POLY_distance1_val = distance(v_POLY_null2_val, v_POLY_param1_val);\n\t\n\t// /particles/particlesSystemGpu1/random1\n\tfloat v_POLY_random1_rand = rand(v_POLY_floatToVec2_1_vec2);\n\t\n\t// /particles/particlesSystemGpu1/random2\n\tfloat v_POLY_random2_rand = rand(v_POLY_floatToVec2_2_vec2);\n\t\n\t// /particles/particlesSystemGpu1/ramp1\n\tfloat v_POLY_ramp1_val = texture2D(v_POLY_ramp_ramp1, vec2(v_POLY_distance1_val, 0.0)).x;\n\t\n\t// /particles/particlesSystemGpu1/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_random2_rand, 0.04, 0.13);\n\t\n\t// /particles/particlesSystemGpu1/mult1\n\tfloat v_POLY_mult1_product = (v_POLY_ramp1_val * v_POLY_random1_rand * 1.0);\n\t\n\t// /particles/particlesSystemGpu1/add2\n\tfloat v_POLY_add2_sum = (v_POLY_attribute_state_IN_val + v_POLY_ramp1_val + 0.0);\n\t\n\t// /particles/particlesSystemGpu1/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_multScalar1_val, v_POLY_param2_val, v_POLY_mult1_product);\n\t\n\t// /particles/particlesSystemGpu1/subtract1\n\tfloat v_POLY_subtract1_subtract = (v_POLY_add2_sum - 0.01);\n\t\n\t// /particles/particlesSystemGpu1/maxLength1\n\tvec3 v_POLY_maxLength1_val = maxLength(v_POLY_mix1_mix, 4.0);\n\t\n\t// /particles/particlesSystemGpu1/clamp1\n\tfloat v_POLY_clamp1_val = clamp(v_POLY_subtract1_subtract, 0.0, 1.0);\n\t\n\t// /particles/particlesSystemGpu1/acceleration1\n\tvec3 v_POLY_acceleration1_velocity = velFromAccel(v_POLY_maxLength1_val, vec3(0.0, 0.0, 0.0), 1.0, delta_time);\n\tvec3 v_POLY_acceleration1_position = posFromVel(v_POLY_null1_val, v_POLY_acceleration1_velocity, delta_time);\n\t\n\t// /particles/particlesSystemGpu1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_clamp1_val);\n\t\n\t// /particles/particlesSystemGpu1/multAdd2\n\tfloat v_POLY_multAdd2_val = (0.06*(v_POLY_complement1_val + v_POLY_fitFrom01_1_val)) + 0.0;\n\t\n\t// /particles/particlesSystemGpu1/output1\n\tgl_FragColor.xyz = v_POLY_acceleration1_velocity;\n\t\n\t// /particles/particlesSystemGpu1/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_acceleration1_position, v_POLY_attribute4_val, v_POLY_multAdd2_val);\n\n\n\n\n}"}},"jsFunctionBodies":{"/particles/actor_particles1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor_particles1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonScenePause() {\n\t\tthis.onScenePause1();\n\t}\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor_particles1/onScenePause1\n\tonScenePause1() {\n\t\tthis.particlesSystemReset1(0);\n\t}\n\n\t// /particles/actor_particles1/onTick1\n\tonTick1() {\n\t\tthis.particlesSystemStepSimulation1(0);\n\t}\n\n\t// /particles/actor_particles1/particlesSystemReset1\n\tparticlesSystemReset1() {\n\t\tparticlesSystemReset(this.object3D);\n\t}\n\n\t// /particles/actor_particles1/particlesSystemStepSimulation1\n\tparticlesSystemStepSimulation1() {\n\t\tparticlesSystemStepSimulation(this.object3D, { texture_: this.v_POLY_particlesSystemStepSimulation1_ });\n\t}\n}\nreturn CustomActorEvaluator;\n","/particles/actor_OLD":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor1/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /particles/actor1/plane1\n\tv_POLY_plane1_Plane = computed(() => planeSet(VAR__plane1_normal.set(0, 0, 1), 0.0, VAR__plane1__1));\n\n\t// /particles/actor1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor1/rayIntersectPlane1\n\tv_POLY_rayIntersectPlane1_position = computed(() =>\n\t\trayIntersectPlane(this.v_POLY_rayFromCursor1_Ray.value, this.v_POLY_plane1_Plane.value, VAR__rayIntersectPlane1_)\n\t);\n\n\t// /particles/actor1/divide2\n\tv_POLY_divide2_divide = computed(() => divideNumber(1.0, this.v_POLY_onTick1_delta.value, 1.0));\n\n\t// /particles/actor1/previousValue1\n\tv_POLY_previousValue1_prev = computed(() =>\n\t\tpreviousValueVector3(\n\t\t\t\"/particles/actor1/previousValue1\",\n\t\t\t1.0,\n\t\t\tVAR__previousValue1_current.copy(this.v_POLY_rayIntersectPlane1_position.value)\n\t\t)\n\t);\n\n\t// /particles/actor1/null1\n\tv_POLY_null1_out = computed(() => VAR__null1_in.copy(this.v_POLY_rayIntersectPlane1_position.value));\n\n\t// /particles/actor1/subtract2\n\tv_POLY_subtract2_sub = computed(() =>\n\t\tsubtractVector(\n\t\t\tVAR__subtract2_sub0.copy(this.v_POLY_rayIntersectPlane1_position.value),\n\t\t\tVAR__subtract2_sub1.copy(this.v_POLY_previousValue1_prev.value),\n\t\t\tVAR__subtract2_sub2.set(0, 0, 0)\n\t\t)\n\t);\n\n\t// /particles/actor1/multScalar1\n\tv_POLY_multScalar1_val = computed(() =>\n\t\tmultScalarVector3(\n\t\t\tVAR__multScalar1_value.copy(this.v_POLY_subtract2_sub.value),\n\t\t\tthis.v_POLY_divide2_divide.value,\n\t\t\tVAR__multScalar1__1\n\t\t)\n\t);\n\n\t// /particles/actor1/setParam2\n\tv_POLY_setParam2_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/velocity\"));\n\n\t// /particles/actor1/setParam1\n\tv_POLY_setParam1_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/cursor\"));\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor1/onTick1\n\tonTick1() {\n\t\tthis.setParam2(0);\n\t}\n\n\t// /particles/actor1/setParam2\n\tsetParam2() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam2_getParamSinceNoInput.value,\n\t\t\tVAR__setParam2_val.copy(this.v_POLY_multScalar1_val.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setParam1(0);\n\t}\n\n\t// /particles/actor1/setParam1\n\tsetParam1() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam1_getParamSinceNoInput.value,\n\t\t\tVAR__setParam1_val.copy(this.v_POLY_null1_out.value),\n\t\t\t1.0\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n","/particles/actor1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /particles/actor2/getObject1\n\tv_POLY_getObject1_Object3D = computed(() => getObject(this.object3D, false, \"*/curve\"));\n\n\t// /particles/actor2/onTick2\n\tv_POLY_onTick2_time = computed(() => globalsTime());\n\tv_POLY_onTick2_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor2/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /particles/actor2/plane1\n\tv_POLY_plane1_Plane = computed(() => planeSet(VAR__plane1_normal.set(0, 0, 1), 0.0, VAR__plane1__1));\n\n\t// /particles/actor2/param1\n\tv_POLY_param1_val = computed(() => getActorNodeParamValue(\"useCursor\"));\n\n\t// /particles/actor2/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /particles/actor2/getObjectUserData1\n\tv_POLY_getObjectUserData1_val = computed(() => getObjectUserData(this.v_POLY_getObject1_Object3D.value, \"path\"));\n\n\t// /particles/actor2/multAdd1\n\tv_POLY_multAdd1_val = computed(() => mathFloat_4(multAdd, this.v_POLY_onTick2_time.value, 0.0, 0.25, 0.0));\n\n\t// /particles/actor2/rayIntersectPlane1\n\tv_POLY_rayIntersectPlane1_position = computed(() =>\n\t\trayIntersectPlane(this.v_POLY_rayFromCursor1_Ray.value, this.v_POLY_plane1_Plane.value, VAR__rayIntersectPlane1_)\n\t);\n\n\t// /particles/actor2/divide2\n\tv_POLY_divide2_divide = computed(() => divideNumber(1.0, this.v_POLY_onTick1_delta.value, 1.0));\n\n\t// /particles/actor2/mod1\n\tv_POLY_mod1_mod = computed(() => mathFloat_2(mod, this.v_POLY_multAdd1_val.value, 1.0));\n\n\t// /particles/actor2/catmullRomCurve3GetPoint1\n\tv_POLY_catmullRomCurve3GetPoint1_position = computed(() =>\n\t\tcatmullRomCurve3GetPoint(\n\t\t\tthis.v_POLY_getObjectUserData1_val.value,\n\t\t\tthis.v_POLY_mod1_mod.value,\n\t\t\tVAR__catmullRomCurve3GetPoint1_\n\t\t)\n\t);\n\n\t// /particles/actor2/mix1\n\tv_POLY_mix1_mix = computed(() =>\n\t\tmathVector3_3vvf(\n\t\t\tmix,\n\t\t\tVAR__mix1_value0.copy(this.v_POLY_catmullRomCurve3GetPoint1_position.value),\n\t\t\tVAR__mix1_value1.copy(this.v_POLY_rayIntersectPlane1_position.value),\n\t\t\tthis.v_POLY_param1_val.value,\n\t\t\tVAR__mix1_\n\t\t)\n\t);\n\n\t// /particles/actor2/null2\n\tv_POLY_null2_out = computed(() => VAR__null2_in.copy(this.v_POLY_mix1_mix.value));\n\n\t// /particles/actor2/previousValue1\n\tv_POLY_previousValue1_prev = computed(() =>\n\t\tpreviousValueVector3(\n\t\t\t\"/particles/actor2/previousValue1\",\n\t\t\t1.0,\n\t\t\tVAR__previousValue1_current.copy(this.v_POLY_null2_out.value)\n\t\t)\n\t);\n\n\t// /particles/actor2/null1\n\tv_POLY_null1_out = computed(() => VAR__null1_in.copy(this.v_POLY_null2_out.value));\n\n\t// /particles/actor2/subtract2\n\tv_POLY_subtract2_sub = computed(() =>\n\t\tsubtractVector(\n\t\t\tVAR__subtract2_sub0.copy(this.v_POLY_null2_out.value),\n\t\t\tVAR__subtract2_sub1.copy(this.v_POLY_previousValue1_prev.value),\n\t\t\tVAR__subtract2_sub2.set(0, 0, 0)\n\t\t)\n\t);\n\n\t// /particles/actor2/null3\n\tv_POLY_null3_out = computed(() => VAR__null3_in.copy(this.v_POLY_null1_out.value));\n\n\t// /particles/actor2/multScalar1\n\tv_POLY_multScalar1_val = computed(() =>\n\t\tmultScalarVector3(\n\t\t\tVAR__multScalar1_value.copy(this.v_POLY_subtract2_sub.value),\n\t\t\tthis.v_POLY_divide2_divide.value,\n\t\t\tVAR__multScalar1__1\n\t\t)\n\t);\n\n\t// /particles/actor2/setParam1\n\tv_POLY_setParam1_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/cursor\"));\n\n\t// /particles/actor2/setParam2\n\tv_POLY_setParam2_getParamSinceNoInput = computed(() => getParam(\"/particles/particlesSystemGpu1/velocity\"));\n\n\t// /particles/actor2/getObject2\n\tv_POLY_getObject2_Object3D = computed(() => getObject(this.object3D, false, \"*/debugObject\"));\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /particles/actor2/onTick1\n\tonTick1() {\n\t\tthis.setParam2(0);\n\t}\n\n\t// /particles/actor2/setParam2\n\tsetParam2() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam2_getParamSinceNoInput.value,\n\t\t\tVAR__setParam2_val.copy(this.v_POLY_multScalar1_val.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setParam1(0);\n\t}\n\n\t// /particles/actor2/setParam1\n\tsetParam1() {\n\t\tsetParamVector3(\n\t\t\tthis.v_POLY_setParam1_getParamSinceNoInput.value,\n\t\t\tVAR__setParam1_val.copy(this.v_POLY_null3_out.value),\n\t\t\t1.0\n\t\t);\n\t\tthis.setObjectPosition1(0);\n\t}\n\n\t// /particles/actor2/setObjectPosition1\n\tsetObjectPosition1() {\n\t\tsetObjectPosition(\n\t\t\tthis.v_POLY_getObject2_Object3D.value,\n\t\t\tVAR__setObjectPosition1_position.copy(this.v_POLY_null3_out.value),\n\t\t\t1.0,\n\t\t\ttrue\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n"}}
Code editor
{"multiple_panel":{"split_ratio":0.66,"split_panel0":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5543217692883486,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/perspectiveCamera1","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false,"initLayoutData":{"camera":{"position":{"x":450,"y":-500},"zoom":1},"history":{"2":{"position":{"x":0,"y":0},"zoom":1},"944":{"position":{"x":450,"y":-500},"zoom":1},"1016":{"position":{"x":0,"y":0},"zoom":1},"1530":{"position":{"x":500,"y":-300},"zoom":1},"2654":{"position":{"x":-250,"y":0},"zoom":1}},"paramsDisplayed":false,"linkIndex":1}}}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":238.81028632912466,"y":-1211.5196831494463},"zoom":0.629222106933593},"history":{"2":{"position":{"x":-76.36752721887316,"y":240.76702702674808},"zoom":1.0222221069335933},"944":{"position":{"x":238.81028632912466,"y":-1211.5196831494463},"zoom":0.629222106933593},"1016":{"position":{"x":-37.84077570371631,"y":18.31005275986273},"zoom":0.8192221069335932},"1530":{"position":{"x":-583.4154199432219,"y":-115.40472383762385},"zoom":0.578222106933593},"2654":{"position":{"x":861.2194050196861,"y":-164.63695462438739},"zoom":0.40222210693359295}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"split_panel1":{"panelTypes":["sceneTree"],"currentPanelIndex":0,"panel_data":{"mask":"*"}},"split_mode":"horizontal"},"currentNodes":["/particles","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor_OLD","/particles","/particles/actor1","/particles","/particles/actor1","/particles","/particles/actor1","/particles"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":19,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"createExport":false,"checkRemoteAssetsUse":true,"minimizeFilesCount":false,"compressJs":true,"createZip":false,"runPostExportCommand":false},"paramsModal":[]}
Used nodes
event/cameraOrbitControls;mat/meshBasic;mat/meshBasicBuilder;mat/pointsBuilder;obj/geo;sop/actor;sop/cameraControls;sop/circle;sop/curveFromPoints;sop/instance;sop/materialsNetwork;sop/merge;sop/objectProperties;sop/particlesSystemGpu;sop/perspectiveCamera;sop/point;sop/restAttributes;sop/scatter;sop/sphere;sop/text
Used operations
Used modules
Used assemblers
GL_MESH_BASIC;GL_PARTICLES;GL_POINTS;JS_ACTOR
Used integrations
[]
Used assets
Nodes map
{"/particles":"obj/geo","/particles/MAT":"sop/materialsNetwork","/particles/MAT/meshBasicBuilder_INSTANCES":"mat/meshBasicBuilder","/particles/MAT/meshBasicBuilder_INSTANCES_PARTICLES":"mat/meshBasicBuilder","/particles/MAT/pointsParticles":"mat/pointsBuilder","/particles/MAT/meshBasic_DEBUG_SPHERE":"mat/meshBasic","/particles/actor_particles1":"sop/actor","/particles/instance1":"sop/instance","/particles/particlesSystemGpu1":"sop/particlesSystemGpu","/particles/point1":"sop/point","/particles/restAttributes1":"sop/restAttributes","/particles/scatter1":"sop/scatter","/particles/sphere1":"sop/sphere","/particles/text1":"sop/text","/particles/circle1":"sop/circle","/particles/curveFromPoints1":"sop/curveFromPoints","/particles/objectProperties1":"sop/objectProperties","/particles/merge1":"sop/merge","/particles/circle2":"sop/circle","/particles/objectProperties2":"sop/objectProperties","/particles/actor_OLD":"sop/actor","/particles/actor1":"sop/actor","/cameras":"obj/geo","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/perspectiveCamera1":"sop/perspectiveCamera"}
Js version
Editor version
Engine version
Logout
0%
There was a problem displaying your scene:
view scene source