Name
*
Code
{"properties":{"frame":56248,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT","versions":{"polygonjs":"1.5.32"}},"root":{"type":"root","nodes":{"grid":{"type":"geo","nodes":{"planeHelper1":{"type":"planeHelper","flags":{"display":true}}},"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":false}},"COP":{"type":"copNetwork","nodes":{"builder2DArray1":{"type":"builder2DArray","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"null2","output":"val"},{"index":1,"inputName":"add1","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"null2","output":"val"},{"index":1,"inputName":"add1","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"constant1":{"type":"constant","connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"null1","output":"val"},{"index":1,"inputName":"y","node":"null1","output":"val"},{"index":2,"inputName":"z","node":"null1","output":"val"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[null,null,{"index":2,"inputName":"z","node":"multAdd2","output":"val"}]},"floatToVec3_4":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"constant1","output":"val"},{"index":1,"inputName":"y","node":"constant1","output":"val"},{"index":2,"inputName":"z","node":"constant1","output":"val"}]},"globals1":{"type":"globals"},"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":0.2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"null3","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"}]}},"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":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":-0.1},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"null3","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"}]}},"multAdd3":{"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":0.42},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"layer"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"multAdd4":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]}},"inputs":[{"index":0,"inputName":"value","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multAdd5":{"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}},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.5}},"inputs":[{"index":0,"inputName":"value","node":"noise3","output":"noise"}],"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.55}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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.19}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise1":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.1,0.1,0.1]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[10,0.01,10]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar1","output":"val"},{"index":1,"inputName":"position","node":"add2","output":"sum"},null,{"index":3,"inputName":"offset","node":"floatToVec3_2","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise2":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.95,0.95,0.95]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[2.7,1,2.7]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"floatToVec3_4","output":"vec3"},{"index":1,"inputName":"position","node":"null2","output":"val"},null,{"index":3,"inputName":"offset","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise3":{"type":"noise","params":{"outputType":1,"amp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.42},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[100,100,100]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"amp","type":"float"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"float"}]}},"null1":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"globals1","output":"layer"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"vec2ToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"null3":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"globals1","output":"time"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"color","node":"multAdd4","output":"val"},{"index":1,"inputName":"alpha","node":"multAdd5","output":"val"}]},"vec2ToVec3_1":{"type":"vec2ToVec3","params":{"vec2":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec2","node":"globals1","output":"uv"},{"index":1,"inputName":"z","node":"multAdd3","output":"val"}]}},"persisted_config":{"uniforms":{"uLayer":{"value":3},"time":{"__v_isShallow":false,"__v_isRef":true,"_rawValue":1050.2044666666486,"_value":1050.2044666666486},"resolution":{"value":{"x":128,"y":128}}},"param_uniform_pairs":[],"uniforms_time_dependent":true,"uniforms_resolution_dependent":false}},"envMap":{"type":"envMap","inputs":["imageEnv"]},"imageEnv":{"type":"imageEXR","params":{"url":"https://raw.githubusercontent.com/polygonjs/polygonjs-assets/master/textures/piz_compressed.exr"}},"imageUv":{"type":"image","params":{"url":"https://raw.githubusercontent.com/polygonjs/polygonjs-assets/master/textures/uv.jpg","tflipY":true}}}},"grass":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"lineBasicBuilder_NON_OPTIMISED":{"type":"lineBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"instancePosition","type":2},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"constant1":{"type":"constant","params":{"type":4,"color":[0.011764705882352941,0.10980392156862745,0.01568627450980392],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant2":{"type":"constant","params":{"type":4,"color":[0.25098039215686274,0.4392156862745098,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant3":{"type":"constant","params":{"type":4,"color":[0.4392156862745098,0.4235294117647059,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"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.1},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"val","node":"attribute2","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"position","node":"subnet_length_variation","output":"input0"}]},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false},"raw_input":0.65}},"inputs":[{"index":0,"inputName":"value0","node":"constant1","output":"val"},{"index":1,"inputName":"value1","node":"constant2","output":"val"},{"index":2,"inputName":"blend","node":"fitFrom01_1","output":"val"}],"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}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value0","node":"mix1","output":"mix"},{"index":1,"inputName":"value1","node":"constant3","output":"val"},{"index":2,"inputName":"blend","node":"smoothstep1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"noise1":{"type":"noise","params":{"outputType":1,"amp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.6,0.6,0.6]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"amp","type":"float"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"subnet_noise","output":"input0"},{"index":1,"inputName":"color","node":"varyingRead1","output":"fragment"}]},"smoothstep1":{"type":"smoothstep","params":{"edge0":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.71},"edge1":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.86},"x":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[null,null,{"index":2,"inputName":"x","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"edge0","type":"float"},{"name":"edge1","type":"float"},{"name":"x","type":"float"}],"out":[{"name":"val","type":"float"}]}},"subnet_length_variation":{"type":"subnet","nodes":{"attribute3":{"type":"attribute","params":{"name":"instancePosition","type":2},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"vec3ToFloat1","output":"x"},null,{"index":2,"inputName":"z","node":"vec3ToFloat1","output":"z"}]},"globals1":{"type":"globals"},"length1":{"type":"length","params":{"x":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"x","type":"vec3"}],"out":[{"name":"val","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[1,1,1]}},"inputs":[{"index":0,"inputName":"value","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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":"globals1","output":"position"},{"index":1,"inputName":"mult","node":"length1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise2":{"type":"noise","params":{"outputType":3,"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true}},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[0,3.2,0]}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"subnetOutput1":{"type":"subnetOutput","inputs":[{"index":0,"inputName":"input0","node":"multScalar2","output":"val"}],"connection_points":{"in":[{"name":"input0","type":"vec3"}],"out":[]}},"vec3ToFloat1":{"type":"vec3ToFloat","params":{"vec":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec","node":"attribute3","output":"val"}]}},"params":{"inputType0":4,"input0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"input0","type":"vec3"}],"out":[{"name":"input0","type":"vec3"}]}},"subnet_noise":{"type":"subnet","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"subnetInput1","output":"input0"},{"index":1,"inputName":"add1","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"subnetInput1","output":"input0"},{"index":1,"inputName":"add1","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"attribute1":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"null1","output":"val"},{"index":1,"inputName":"y","node":"null1","output":"val"},{"index":2,"inputName":"z","node":"null1","output":"val"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[null,null,{"index":2,"inputName":"z","node":"multAdd2","output":"val"}]},"globals2":{"type":"globals"},"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":0.2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"time"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","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":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":-0.1},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"time"}],"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.55}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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.19}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise1":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.1,0.1,0.1]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.7,0.1,0.7]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar1","output":"val"},{"index":1,"inputName":"position","node":"add2","output":"sum"},null,{"index":3,"inputName":"offset","node":"floatToVec3_2","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise2":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.95,0.95,0.95]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.19999999999999996,0.19999999999999996,0.19999999999999996]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar2","output":"val"},{"index":1,"inputName":"position","node":"subnetInput1","output":"input0"},null,{"index":3,"inputName":"offset","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"null1":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"subnetInput1":{"type":"subnetInput","connection_points":{"in":[],"out":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}]}},"subnetOutput1":{"type":"subnetOutput","inputs":[{"index":0,"inputName":"input0","node":"add1","output":"sum"}],"connection_points":{"in":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}],"out":[]}}},"params":{"inputsCount":3,"inputType0":4,"inputType1":4,"inputType2":4,"input0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"input1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"input2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"input0","node":"instanceTransform1","output":"position"}],"connection_points":{"in":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}],"out":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}]}},"varyingRead1":{"type":"varyingRead","params":{"name":"basecolor","type":2},"connection_points":{"in":[],"out":[{"name":"fragment","type":"vec3"}]}},"varyingWrite1":{"type":"varyingWrite","params":{"name":"basecolor","type":2,"vertex":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"vertex","node":"mix2","output":"mix"}],"connection_points":{"in":[{"name":"vertex","type":"vec3"}],"out":[]}}},"params":{"linewidth":6.5},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-main","type":"LineBasicMaterial","color":16777215,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"linewidth":6.5},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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},"referencePosition":{"type":"v3","value":[0,0,0]},"nearDistance":{"value":1},"farDistance":{"value":1000}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","fragmentShader":"\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#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\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","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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}},"defines":{"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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":{"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}},"defines":{"DEPTH_PACKING":3200},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"lineBasicBuilder_OPTIMISED":{"type":"lineBasicBuilder","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"add1","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute3":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute4":{"type":"attribute","params":{"name":"ptuv","type":1},"connection_points":{"in":[],"out":[{"name":"val","type":"vec2"}]}},"constant1":{"type":"constant","params":{"type":4,"color":[0.011764705882352941,0.10980392156862745,0.01568627450980392],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant2":{"type":"constant","params":{"type":4,"color":[0.25098039215686274,0.4392156862745098,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant4":{"type":"constant","params":{"float":0.15},"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.1},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"val","node":"attribute2","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToInt1":{"type":"floatToInt","params":{"float":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"float","node":"multAdd1","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"constant4","output":"val"},{"index":1,"inputName":"y","node":"constant4","output":"val"},{"index":2,"inputName":"z","node":"constant4","output":"val"}]},"globals1":{"type":"globals"},"globals2":{"type":"globals"},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"position","node":"multScalar1","output":"val"}]},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false},"raw_input":0.65}},"inputs":[{"index":0,"inputName":"value0","node":"constant1","output":"val"},{"index":1,"inputName":"value1","node":"constant2","output":"val"},{"index":2,"inputName":"blend","node":"fitFrom01_1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"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":4},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"attribute3","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"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[-0.5,-0.5,-0.5]},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[2,2,2]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"vec4ToVec3_1","output":"vec3"},null,{"index":2,"inputName":"mult","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multAdd3":{"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},"raw_input":-0.5},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":1.6}},"inputs":[{"index":0,"inputName":"value","node":"vec4ToVec3_1","output":"w"}],"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":false}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"position"},{"index":1,"inputName":"mult","node":"multAdd3","output":"val"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"add1","output":"sum"},{"index":1,"inputName":"color","node":"mix1","output":"mix"}]},"texture2DArray1":{"type":"texture2DArray","params":{"uv":{"overriden_options":{}},"layer":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"attribute4","output":"val"},{"index":1,"inputName":"layer","node":"floatToInt1","output":"int"}]},"vec2ToVec3_1":{"type":"vec2ToVec3","params":{"vec2":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec2","node":"attribute4","output":"val"},{"index":1,"inputName":"z","node":"multAdd1","output":"val"}]},"vec4ToVec3_1":{"type":"vec4ToVec3","params":{"vec4":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec4","node":"texture2DArray1","output":"rgba"}]}},"params":{"linewidth":6.5,"texture3D1":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../../COP/builder2DArray1","overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-main","type":"LineBasicMaterial","color":16777215,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"linewidth":6.5},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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},"referencePosition":{"type":"v3","value":[0,0,0]},"nearDistance":{"value":1},"farDistance":{"value":1000}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","fragmentShader":"\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#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\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","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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}},"defines":{"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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":{"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}},"defines":{"DEPTH_PACKING":3200},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasic_GROUND":{"type":"meshBasic","params":{"color":[0.06274509803921569,0.20392156862745098,0.03529411764705882]}}}},"attribId1":{"type":"attribId","params":{"id":false,"idName":"pt","idnName":"ptn"},"inputs":["line1"]},"attribRename1":{"type":"attribRename","params":{"oldName":"uv","newName":"ptuv"},"inputs":["scatter1"]},"instance1":{"type":"instance","params":{"attributesToCopy":"instance* id* ptn ptuv","material":"../MAT/lineBasicBuilder_OPTIMISED"},"inputs":["attribId1","attribRename1"],"flags":{"display":true}},"instance2":{"type":"instance","params":{"attributesToCopy":"instance* id* ptn ptuv","material":"../MAT/lineBasicBuilder_NON_OPTIMISED"},"inputs":["attribId1","attribRename1"]},"line1":{"type":"line","params":{"pointsCount":5,"direction":[0,0,1]}},"scatter1":{"type":"scatter","params":{"pointsCount":200000,"transferAttributes":true,"attributesToTransfer":"uv"},"inputs":["objectMerge1"]},"objectMerge1":{"type":"objectMerge","params":{"geometry":"../../ground/OUT"}}},"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}},"sky":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"sky1":{"type":"sky"}}},"material1":{"type":"material","params":{"material":"../MAT/sky1"},"inputs":["sphere1"],"flags":{"display":true}},"sphere1":{"type":"sphere","params":{"radius":1000}}},"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}},"ground":{"type":"geo","nodes":{"BVH1":{"type":"BVH","inputs":["OUT"]},"MAT":{"type":"materialsNetwork","nodes":{"meshBasic_GROUND":{"type":"meshBasic","params":{"color":[0.06274509803921569,0.20392156862745098,0.03529411764705882]}},"meshLambert_GROUND":{"type":"meshLambert","params":{"color":[0.010960094003125918,0.11443537381770343,0.011612245176281512]}}}},"OUT":{"type":"null","inputs":["transform1"]},"material1":{"type":"material","params":{"material":"../MAT/meshLambert_GROUND"},"inputs":["OUT"]},"noise1":{"type":"noise","params":{"amplitude":4.9,"freq":[-0.0060000000000000366,-0.0060000000000000366,-0.0060000000000000366],"offset":[0,0,26.7],"ampAttenuation":0.1,"freqIncrease":0.3,"seed":16,"useNormals":true},"inputs":["plane1"]},"plane1":{"type":"plane","params":{"size":[200,300],"stepSize":1.2,"center":[14.651343247698263,-7.775128346119189,0]}},"transform1":{"type":"transform","params":{"t":[0,2.9124666555513055,0]},"inputs":["noise1"]},"oceanPlane1":{"type":"oceanPlane","params":{"size":66},"inputs":["plane2"]},"plane2":{"type":"plane","params":{"size":[661,666],"useSegmentsCount":1,"stepSize":2,"center":[0,-11.3,0]}},"merge1":{"type":"merge","inputs":["oceanPlane1","material1"],"flags":{"display":true}}},"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":{"maxDistance":260,"target":[-33.62544586106904,-65.67812610218134,24.271132065270567]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera_DEFAULT"]},"cameraControls2":{"type":"cameraControls","nodes":{"firstPersonControls1":{"type":"firstPersonControls","params":{"colliderObject":"../../../ground/BVH1","capsuleHeight":2.3,"translateSpeed":2.8,"jumpStrength":33,"runSpeedMult":3.5,"startPosition":[2,8,2]}}},"params":{"node":"firstPersonControls1"},"inputs":["perspectiveCamera_FPS"]},"merge1":{"type":"merge","inputs":["cameraControls1","cameraControls2"],"flags":{"display":true}},"perspectiveCamera_DEFAULT":{"type":"perspectiveCamera","params":{"near":1,"far":1240,"position":[-128.19489384666974,59.37049813773632,170.28509739593437],"rotation":[-40.577241862378756,-26.193755021302916,-20.708017447225334]}},"perspectiveCamera_FPS":{"type":"perspectiveCamera"}},"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}},"lights":{"type":"geo","nodes":{"ambientLight1":{"type":"ambientLight","params":{"intensity":0.2}},"hemisphereLight1":{"type":"hemisphereLight"},"merge1":{"type":"merge","inputs":["ambientLight1","hemisphereLight1"],"flags":{"display":true}}},"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":{"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT"}},"ui":{"nodes":{"grid":{"pos":[50,-250],"nodes":{"planeHelper1":{"pos":[0,0]}}},"COP":{"pos":[-150,350],"nodes":{"builder2DArray1":{"pos":[-100,400],"nodes":{"add1":{"pos":[550,250]},"add2":{"pos":[150,400]},"constant1":{"pos":[-300,300]},"floatToVec3_1":{"pos":[-450,750]},"floatToVec3_2":{"pos":[-450,500]},"floatToVec3_3":{"pos":[-450,350]},"floatToVec3_4":{"pos":[-200,300]},"globals1":{"pos":[-1000,300]},"multAdd1":{"pos":[-550,500]},"multAdd2":{"pos":[-550,350]},"multAdd3":{"pos":[-700,200]},"multAdd4":{"pos":[550,500]},"multAdd5":{"pos":[450,700]},"multScalar1":{"pos":[-50,750]},"multScalar2":{"pos":[-300,600]},"noise1":{"pos":[300,500]},"noise2":{"pos":[-50,400]},"noise3":{"pos":[300,700]},"null1":{"pos":[-550,750]},"null2":{"pos":[-200,200]},"null3":{"pos":[-750,350]},"output1":{"pos":[700,500]},"vec2ToVec3_1":{"pos":[-550,100]}}},"envMap":{"pos":[50,200]},"imageEnv":{"pos":[50,100]},"imageUv":{"pos":[-100,100]}}},"grass":{"pos":[50,150],"nodes":{"MAT":{"pos":[-450,500],"nodes":{"lineBasicBuilder_NON_OPTIMISED":{"pos":[0,100],"nodes":{"attribute1":{"pos":[-800,700]},"attribute2":{"pos":[-750,500]},"constant1":{"pos":[-750,300]},"constant2":{"pos":[-750,400]},"constant3":{"pos":[-450,550]},"fitFrom01_1":{"pos":[-600,500]},"instanceTransform1":{"pos":[-350,-100]},"mix1":{"pos":[-350,350]},"mix2":{"pos":[-250,450]},"noise1":{"pos":[-650,700]},"output1":{"pos":[500,150]},"smoothstep1":{"pos":[-450,700]},"subnet_length_variation":{"pos":[-550,-100],"nodes":{"attribute3":{"pos":[-1550,-50]},"floatToVec3_3":{"pos":[-1300,-50]},"globals1":{"pos":[-1500,-350]},"length1":{"pos":[-900,-150]},"multAdd2":{"pos":[-1050,-50]},"multScalar2":{"pos":[-800,-300]},"noise2":{"pos":[-1150,-50]},"subnetOutput1":{"pos":[-600,-300]},"vec3ToFloat1":{"pos":[-1400,-50]}}},"subnet_noise":{"pos":[-150,-100],"nodes":{"add1":{"pos":[-200,-150]},"add2":{"pos":[-800,-350]},"attribute1":{"pos":[-1150,350]},"floatToVec3_1":{"pos":[-900,200]},"floatToVec3_2":{"pos":[-1100,-50]},"floatToVec3_3":{"pos":[-1050,-200]},"globals2":{"pos":[-1350,-150]},"multAdd1":{"pos":[-1200,-50]},"multAdd2":{"pos":[-1150,-200]},"multScalar1":{"pos":[-700,200]},"multScalar2":{"pos":[-850,50]},"noise1":{"pos":[-350,-50]},"noise2":{"pos":[-900,-300]},"null1":{"pos":[-1000,200]},"subnetInput1":{"pos":[-1100,-300]},"subnetOutput1":{"pos":[0,-200]}}},"varyingRead1":{"pos":[250,350]},"varyingWrite1":{"pos":[-150,450],"comment":"using the varyingWrite/varyingRead instead of setting the color directly allows us to set the color in the vertex shader, as opposed to the fragment shader, which would be less performant."}}},"lineBasicBuilder_OPTIMISED":{"pos":[0,0],"nodes":{"add1":{"pos":[350,-400]},"attribute2":{"pos":[-750,500]},"attribute3":{"pos":[-800,-50]},"attribute4":{"pos":[-800,-200]},"constant1":{"pos":[-750,300]},"constant2":{"pos":[-750,400]},"constant4":{"pos":[-350,0]},"fitFrom01_1":{"pos":[-600,500]},"floatToInt1":{"pos":[-550,-50]},"floatToVec3_1":{"pos":[-250,0]},"globals1":{"pos":[-900,-200]},"globals2":{"pos":[-550,-550]},"instanceTransform1":{"pos":[150,-600]},"mix1":{"pos":[-350,350]},"multAdd1":{"pos":[-650,-50]},"multAdd2":{"pos":[-100,-200]},"multAdd3":{"pos":[-200,-450]},"multScalar1":{"pos":[-100,-550]},"output1":{"pos":[650,0]},"texture2DArray1":{"pos":[-400,-200]},"vec2ToVec3_1":{"pos":[-550,-150]},"vec4ToVec3_1":{"pos":[-250,-200]}}},"meshBasic_GROUND":{"pos":[0,250]}}},"attribId1":{"pos":[-350,300]},"attribRename1":{"pos":[-100,400]},"instance1":{"pos":[-350,650],"comment":"this demo includes 2 different shaders for the grass. the one currently displayed is optimised, as it reads the noise from a 3D texture. But that comes at a visual cost, as there is less variation in that noise."},"instance2":{"pos":[100,600],"comment":"If you set the display flag on that node, you can see the less optimised, but nicer grass. It is less optimised as the noise is calculated for every vertex, and not inside a texture. But that allows nicer variation."},"line1":{"pos":[-350,100]},"scatter1":{"pos":[50,200]},"objectMerge1":{"pos":[-50,50]}}},"sky":{"pos":[50,-350],"nodes":{"MAT":{"pos":[-350,350],"nodes":{"sky1":{"pos":[-50,100]}}},"material1":{"pos":[-150,350],"comment":"here we assign the sky material to the sphere"},"sphere1":{"pos":[-150,-100],"comment":"in order to have a sky that always appears to be far enough, we set the radius of the sphere to a large value, like 1000 in this case.\\n\\nThe material is set with depthWrite=false, so the far plane of the camera can remain closer than the radius."}}},"ground":{"pos":[50,-150],"comment":"the changes here are:\\n- replaced the meshBasic material by the meshLambert, as the meshBasic does not react to light\\n- merged the oceanPlane with the ground, and make the plane larger than the grass\\n- increased the size of the oceanPlane","selection":["oceanPlane1"],"nodes":{"BVH1":{"pos":[250,450]},"MAT":{"pos":[-650,550],"selection":["meshLambert_GROUND"],"nodes":{"meshBasic_GROUND":{"pos":[0,200]},"meshLambert_GROUND":{"pos":[0,350]}}},"OUT":{"pos":[0,300]},"material1":{"pos":[0,450]},"noise1":{"pos":[0,50]},"plane1":{"pos":[0,-100]},"transform1":{"pos":[0,150]},"oceanPlane1":{"pos":[-400,200]},"plane2":{"pos":[-400,50]},"merge1":{"pos":[-250,650]}}},"cameras":{"pos":[50,250],"comment":"For the camera, since the environment is quite large, I've increased the far plane, as well as increased the max distance of the camera controls","nodes":{"cameraControls1":{"pos":[-250,0],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"cameraControls2":{"pos":[100,0],"nodes":{"firstPersonControls1":{"pos":[-50,100]}}},"merge1":{"pos":[-50,250]},"perspectiveCamera_DEFAULT":{"pos":[-250,-150]},"perspectiveCamera_FPS":{"pos":[100,-150]}}},"lights":{"pos":[50,450],"comment":"I've set the lights in here for better organisation","nodes":{"ambientLight1":{"pos":[-150,-50]},"hemisphereLight1":{"pos":[150,0]},"merge1":{"pos":[0,200]}}}}},"shaders":{"/COP/builder2DArray1":{"fragment":"#include <common>\n\nuniform float uLayer;\nuniform vec2 resolution;\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /COP/builder2DArray1/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_COP_builder2DArray1_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /COP/builder2DArray1/noise1\n\nfloat fbm_snoise_COP_builder2DArray1_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /COP/builder2DArray1/noise3\n\nfloat fbm_snoise_COP_builder2DArray1_noise3(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /COP/builder2DArray1/globals1\nuniform float time;\n\n\n\n\n\nvoid main() {\n\n\tvec4 diffuseColor = vec4(0.0,0.0,0.0,1.0);\n\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /COP/builder2DArray1/globals1\n\tfloat v_POLY_globals1_layer = uLayer;\n\tfloat v_POLY_globals1_time = time;\n\tvec2 v_POLY_globals1_uv = vec2(gl_FragCoord.x / (resolution.x-1.), gl_FragCoord.y / (resolution.y-1.));\n\t\n\t// /COP/builder2DArray1/constant1\n\tfloat v_POLY_constant1_val = 0.0;\n\t\n\t// /COP/builder2DArray1/null1\n\tfloat v_POLY_null1_val = v_POLY_globals1_layer;\n\t\n\t// /COP/builder2DArray1/multAdd3\n\tfloat v_POLY_multAdd3_val = (0.42*(v_POLY_globals1_layer + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/null3\n\tfloat v_POLY_null3_val = v_POLY_globals1_time;\n\t\n\t// /COP/builder2DArray1/floatToVec3_4\n\tvec3 v_POLY_floatToVec3_4_vec3 = vec3(v_POLY_constant1_val, v_POLY_constant1_val, v_POLY_constant1_val);\n\t\n\t// /COP/builder2DArray1/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_null1_val, v_POLY_null1_val, v_POLY_null1_val);\n\t\n\t// /COP/builder2DArray1/vec2ToVec3_1\n\tvec3 v_POLY_vec2ToVec3_1_vec3 = vec3(v_POLY_globals1_uv.xy, v_POLY_multAdd3_val);\n\t\n\t// /COP/builder2DArray1/multAdd2\n\tfloat v_POLY_multAdd2_val = (-0.1*(v_POLY_null3_val + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/multAdd1\n\tfloat v_POLY_multAdd1_val = (0.2*(v_POLY_null3_val + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.55*v_POLY_floatToVec3_1_vec3);\n\t\n\t// /COP/builder2DArray1/null2\n\tvec3 v_POLY_null2_val = v_POLY_vec2ToVec3_1_vec3;\n\t\n\t// /COP/builder2DArray1/floatToVec3_3\n\tvec3 v_POLY_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_multAdd2_val);\n\t\n\t// /COP/builder2DArray1/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_multAdd1_val, 0.0, 0.0);\n\t\n\t// /COP/builder2DArray1/noise2\n\tfloat v_POLY_noise2_noisex = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\tfloat v_POLY_noise2_noisey = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\tfloat v_POLY_noise2_noisez = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\tvec3 v_POLY_noise2_noise = vec3(v_POLY_noise2_noisex, v_POLY_noise2_noisey, v_POLY_noise2_noisez);\n\t\n\t// /COP/builder2DArray1/add2\n\tvec3 v_POLY_add2_sum = (v_POLY_null2_val + v_POLY_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t// /COP/builder2DArray1/noise1\n\tfloat v_POLY_noise1_noisex = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\tfloat v_POLY_noise1_noisey = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\tfloat v_POLY_noise1_noisez = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\tvec3 v_POLY_noise1_noise = vec3(v_POLY_noise1_noisex, v_POLY_noise1_noisey, v_POLY_noise1_noisez);\n\t\n\t// /COP/builder2DArray1/noise3\n\tfloat v_POLY_noise3_noise = 0.42*fbm_snoise_COP_builder2DArray1_noise3((v_POLY_add2_sum*vec3(100.0, 100.0, 100.0))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /COP/builder2DArray1/multAdd4\n\tvec3 v_POLY_multAdd4_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_noise1_noise + vec3(0.0, 0.0, 0.0))) + vec3(0.5, 0.5, 0.5);\n\t\n\t// /COP/builder2DArray1/multAdd5\n\tfloat v_POLY_multAdd5_val = (1.0*(v_POLY_noise3_noise + 0.0)) + 0.5;\n\t\n\t// /COP/builder2DArray1/output1\n\tdiffuseColor.xyz = v_POLY_multAdd4_val;\n\tdiffuseColor.a = v_POLY_multAdd5_val;\n\n\n\n\n\tgl_FragColor = vec4( diffuseColor );\n}"},"/grass/MAT/lineBasicBuilder_NON_OPTIMISED":{"vertex":"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n#include <uv_pars_vertex>\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>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_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\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\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 <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\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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","customDepthMaterial.vertex":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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"},"/grass/MAT/lineBasicBuilder_OPTIMISED":{"vertex":"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n#include <uv_pars_vertex>\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>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_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\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\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 <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\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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","customDepthMaterial.vertex":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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"}},"jsFunctionBodies":{}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.6025492468134415,"split_panel0":{"panelTypes":["viewer","params","network"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false}}},"split_panel1":{"panelTypes":["viewer","params","network"],"currentPanelIndex":1,"panel_data":{"active_folder":2218,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["viewer","params","network"],"currentPanelIndex":2,"panel_data":{"camera":{"position":{"x":-121.50309703203713,"y":-118.12187259785398},"zoom":0.8785286562709399},"history":{"2":{"position":{"x":-121.50309703203713,"y":-118.12187259785398},"zoom":0.8785286562709399},"128":{"position":{"x":32.92599803895985,"y":-352.77896810911204},"zoom":0.8785286562709399},"272":{"position":{"x":139.83803624067164,"y":-393.8531007867804},"zoom":0.8505286562709399},"344":{"position":{"x":88.65920156883212,"y":-88.70107111169102},"zoom":0.8785286562709399},"596":{"position":{"x":107.13906558,"y":-565.8694901399999},"zoom":0.7620789513793633},"668":{"position":{"x":0,"y":-125},"zoom":0.7620789513793633},"2115":{"position":{"x":-84.23174300779809,"y":-256.9133398701339},"zoom":0.8785286562709399},"2281":{"position":{"x":-35.39402173913044,"y":-144.90489130434787},"zoom":1.1615286562709395},"2319":{"position":{"x":0,"y":0},"zoom":0.8785286562709399},"2484":{"position":{"x":9.106134379221416,"y":-43.25413830130172},"zoom":0.8785286562709399}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/","/grass","/grass","/grass","/grass","/grass","/grass","/grass"],"navigationHistory":{"nodePaths":{"1":["/ground","/","/grass","/","/ground","/","/grass","/","/ground","/","/cameras","/cameras/cameraControls1","/cameras","/","/ground","/","/cameras","/","/ground","/"],"2":["/grass"],"3":["/grass"],"4":["/grass"],"5":["/grass"],"6":["/grass"],"7":["/grass"],"8":["/grass"]},"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
cop/builder2DArray;cop/envMap;cop/image;cop/imageEXR;event/cameraOrbitControls;event/firstPersonControls;mat/lineBasicBuilder;mat/meshBasic;mat/meshLambert;mat/sky;obj/copNetwork;obj/geo;sop/BVH;sop/ambientLight;sop/attribId;sop/attribRename;sop/cameraControls;sop/hemisphereLight;sop/instance;sop/line;sop/material;sop/materialsNetwork;sop/merge;sop/noise;sop/null;sop/objectMerge;sop/oceanPlane;sop/perspectiveCamera;sop/plane;sop/planeHelper;sop/scatter;sop/sphere;sop/transform
Used operations
Used modules
Used assemblers
GL_LINE;GL_TEXTURE_2D_ARRAY
Used integrations
[]
Used assets
Nodes map
{"/grid":"obj/geo","/grid/planeHelper1":"sop/planeHelper","/COP":"obj/copNetwork","/COP/builder2DArray1":"cop/builder2DArray","/COP/envMap":"cop/envMap","/COP/imageEnv":"cop/imageEXR","/COP/imageUv":"cop/image","/grass":"obj/geo","/grass/MAT":"sop/materialsNetwork","/grass/MAT/lineBasicBuilder_NON_OPTIMISED":"mat/lineBasicBuilder","/grass/MAT/lineBasicBuilder_OPTIMISED":"mat/lineBasicBuilder","/grass/MAT/meshBasic_GROUND":"mat/meshBasic","/grass/attribId1":"sop/attribId","/grass/attribRename1":"sop/attribRename","/grass/instance1":"sop/instance","/grass/instance2":"sop/instance","/grass/line1":"sop/line","/grass/scatter1":"sop/scatter","/grass/objectMerge1":"sop/objectMerge","/sky":"obj/geo","/sky/MAT":"sop/materialsNetwork","/sky/MAT/sky1":"mat/sky","/sky/material1":"sop/material","/sky/sphere1":"sop/sphere","/ground":"obj/geo","/ground/BVH1":"sop/BVH","/ground/MAT":"sop/materialsNetwork","/ground/MAT/meshBasic_GROUND":"mat/meshBasic","/ground/MAT/meshLambert_GROUND":"mat/meshLambert","/ground/OUT":"sop/null","/ground/material1":"sop/material","/ground/noise1":"sop/noise","/ground/plane1":"sop/plane","/ground/transform1":"sop/transform","/ground/oceanPlane1":"sop/oceanPlane","/ground/plane2":"sop/plane","/ground/merge1":"sop/merge","/cameras":"obj/geo","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/cameraControls2":"sop/cameraControls","/cameras/cameraControls2/firstPersonControls1":"event/firstPersonControls","/cameras/merge1":"sop/merge","/cameras/perspectiveCamera_DEFAULT":"sop/perspectiveCamera","/cameras/perspectiveCamera_FPS":"sop/perspectiveCamera","/lights":"obj/geo","/lights/ambientLight1":"sop/ambientLight","/lights/hemisphereLight1":"sop/hemisphereLight","/lights/merge1":"sop/merge"}
Js version
Editor version
Engine version
Name
*
Code
{"properties":{"frame":56248,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT","versions":{"polygonjs":"1.5.32"}},"root":{"type":"root","nodes":{"grid":{"type":"geo","nodes":{"planeHelper1":{"type":"planeHelper","flags":{"display":true}}},"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":false}},"COP":{"type":"copNetwork","nodes":{"builder2DArray1":{"type":"builder2DArray","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"null2","output":"val"},{"index":1,"inputName":"add1","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"null2","output":"val"},{"index":1,"inputName":"add1","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"constant1":{"type":"constant","connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"null1","output":"val"},{"index":1,"inputName":"y","node":"null1","output":"val"},{"index":2,"inputName":"z","node":"null1","output":"val"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[null,null,{"index":2,"inputName":"z","node":"multAdd2","output":"val"}]},"floatToVec3_4":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"constant1","output":"val"},{"index":1,"inputName":"y","node":"constant1","output":"val"},{"index":2,"inputName":"z","node":"constant1","output":"val"}]},"globals1":{"type":"globals"},"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":0.2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"null3","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"}]}},"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":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":-0.1},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"null3","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"}]}},"multAdd3":{"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":0.42},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"layer"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"multAdd4":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]}},"inputs":[{"index":0,"inputName":"value","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multAdd5":{"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}},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.5}},"inputs":[{"index":0,"inputName":"value","node":"noise3","output":"noise"}],"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.55}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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.19}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise1":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.1,0.1,0.1]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[10,0.01,10]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar1","output":"val"},{"index":1,"inputName":"position","node":"add2","output":"sum"},null,{"index":3,"inputName":"offset","node":"floatToVec3_2","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise2":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.95,0.95,0.95]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[2.7,1,2.7]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"floatToVec3_4","output":"vec3"},{"index":1,"inputName":"position","node":"null2","output":"val"},null,{"index":3,"inputName":"offset","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise3":{"type":"noise","params":{"outputType":1,"amp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.42},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[100,100,100]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"amp","type":"float"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"float"}]}},"null1":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"globals1","output":"layer"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"null2":{"type":"null","params":{"in":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"vec2ToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"in","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"null3":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"globals1","output":"time"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"color","node":"multAdd4","output":"val"},{"index":1,"inputName":"alpha","node":"multAdd5","output":"val"}]},"vec2ToVec3_1":{"type":"vec2ToVec3","params":{"vec2":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec2","node":"globals1","output":"uv"},{"index":1,"inputName":"z","node":"multAdd3","output":"val"}]}},"persisted_config":{"uniforms":{"uLayer":{"value":3},"time":{"__v_isShallow":false,"__v_isRef":true,"_rawValue":1050.2044666666486,"_value":1050.2044666666486},"resolution":{"value":{"x":128,"y":128}}},"param_uniform_pairs":[],"uniforms_time_dependent":true,"uniforms_resolution_dependent":false}},"envMap":{"type":"envMap","inputs":["imageEnv"]},"imageEnv":{"type":"imageEXR","params":{"url":"https://raw.githubusercontent.com/polygonjs/polygonjs-assets/master/textures/piz_compressed.exr"}},"imageUv":{"type":"image","params":{"url":"https://raw.githubusercontent.com/polygonjs/polygonjs-assets/master/textures/uv.jpg","tflipY":true}}}},"grass":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"lineBasicBuilder_NON_OPTIMISED":{"type":"lineBasicBuilder","nodes":{"attribute1":{"type":"attribute","params":{"name":"instancePosition","type":2},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"constant1":{"type":"constant","params":{"type":4,"color":[0.011764705882352941,0.10980392156862745,0.01568627450980392],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant2":{"type":"constant","params":{"type":4,"color":[0.25098039215686274,0.4392156862745098,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant3":{"type":"constant","params":{"type":4,"color":[0.4392156862745098,0.4235294117647059,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"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.1},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"val","node":"attribute2","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"position","node":"subnet_length_variation","output":"input0"}]},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false},"raw_input":0.65}},"inputs":[{"index":0,"inputName":"value0","node":"constant1","output":"val"},{"index":1,"inputName":"value1","node":"constant2","output":"val"},{"index":2,"inputName":"blend","node":"fitFrom01_1","output":"val"}],"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}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"value0","node":"mix1","output":"mix"},{"index":1,"inputName":"value1","node":"constant3","output":"val"},{"index":2,"inputName":"blend","node":"smoothstep1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"vec3"}]}},"noise1":{"type":"noise","params":{"outputType":1,"amp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.6,0.6,0.6]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"amp","type":"float"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"float"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"subnet_noise","output":"input0"},{"index":1,"inputName":"color","node":"varyingRead1","output":"fragment"}]},"smoothstep1":{"type":"smoothstep","params":{"edge0":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.71},"edge1":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":0.86},"x":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[null,null,{"index":2,"inputName":"x","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"edge0","type":"float"},{"name":"edge1","type":"float"},{"name":"x","type":"float"}],"out":[{"name":"val","type":"float"}]}},"subnet_length_variation":{"type":"subnet","nodes":{"attribute3":{"type":"attribute","params":{"name":"instancePosition","type":2},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"vec3ToFloat1","output":"x"},null,{"index":2,"inputName":"z","node":"vec3ToFloat1","output":"z"}]},"globals1":{"type":"globals"},"length1":{"type":"length","params":{"x":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"x","type":"vec3"}],"out":[{"name":"val","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[1,1,1]}},"inputs":[{"index":0,"inputName":"value","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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":"globals1","output":"position"},{"index":1,"inputName":"mult","node":"length1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise2":{"type":"noise","params":{"outputType":3,"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true}},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.5,0.5,0.5]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[0,3.2,0]}},"maxInputsCount":4,"inputs":[null,{"index":1,"inputName":"position","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"subnetOutput1":{"type":"subnetOutput","inputs":[{"index":0,"inputName":"input0","node":"multScalar2","output":"val"}],"connection_points":{"in":[{"name":"input0","type":"vec3"}],"out":[]}},"vec3ToFloat1":{"type":"vec3ToFloat","params":{"vec":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec","node":"attribute3","output":"val"}]}},"params":{"inputType0":4,"input0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":1,"connection_points":{"in":[{"name":"input0","type":"vec3"}],"out":[{"name":"input0","type":"vec3"}]}},"subnet_noise":{"type":"subnet","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"subnetInput1","output":"input0"},{"index":1,"inputName":"add1","node":"noise1","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"add2":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"subnetInput1","output":"input0"},{"index":1,"inputName":"add1","node":"noise2","output":"noise"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"attribute1":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"null1","output":"val"},{"index":1,"inputName":"y","node":"null1","output":"val"},{"index":2,"inputName":"z","node":"null1","output":"val"}]},"floatToVec3_2":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"multAdd1","output":"val"}]},"floatToVec3_3":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[null,null,{"index":2,"inputName":"z","node":"multAdd2","output":"val"}]},"globals2":{"type":"globals"},"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":0.2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"time"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","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":true}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":-0.1},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"time"}],"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.55}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"multScalar2":{"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.19}},"inputs":[{"index":0,"inputName":"value","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"noise1":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.1,0.1,0.1]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.7,0.1,0.7]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar1","output":"val"},{"index":1,"inputName":"position","node":"add2","output":"sum"},null,{"index":3,"inputName":"offset","node":"floatToVec3_2","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"noise2":{"type":"noise","params":{"amp":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[0.95,0.95,0.95]},"position":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"freq":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":true},"raw_input":[0.19999999999999996,0.19999999999999996,0.19999999999999996]},"offset":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"amp","node":"multScalar2","output":"val"},{"index":1,"inputName":"position","node":"subnetInput1","output":"input0"},null,{"index":3,"inputName":"offset","node":"floatToVec3_3","output":"vec3"}],"connection_points":{"in":[{"name":"amp","type":"vec3"},{"name":"position","type":"vec3"},{"name":"freq","type":"vec3"},{"name":"offset","type":"vec3"}],"out":[{"name":"noise","type":"vec3"}]}},"null1":{"type":"null","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"in","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"subnetInput1":{"type":"subnetInput","connection_points":{"in":[],"out":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}]}},"subnetOutput1":{"type":"subnetOutput","inputs":[{"index":0,"inputName":"input0","node":"add1","output":"sum"}],"connection_points":{"in":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}],"out":[]}}},"params":{"inputsCount":3,"inputType0":4,"inputType1":4,"inputType2":4,"input0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"input1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}},"input2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"input0","node":"instanceTransform1","output":"position"}],"connection_points":{"in":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}],"out":[{"name":"input0","type":"vec3"},{"name":"input1","type":"vec3"},{"name":"input2","type":"vec3"}]}},"varyingRead1":{"type":"varyingRead","params":{"name":"basecolor","type":2},"connection_points":{"in":[],"out":[{"name":"fragment","type":"vec3"}]}},"varyingWrite1":{"type":"varyingWrite","params":{"name":"basecolor","type":2,"vertex":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"inputName":"vertex","node":"mix2","output":"mix"}],"connection_points":{"in":[{"name":"vertex","type":"vec3"}],"out":[]}}},"params":{"linewidth":6.5},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-main","type":"LineBasicMaterial","color":16777215,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"linewidth":6.5},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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},"referencePosition":{"type":"v3","value":[0,0,0]},"nearDistance":{"value":1},"farDistance":{"value":1000}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","fragmentShader":"\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#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\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","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[],"timeDependent":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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}},"defines":{"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_NON_OPTIMISED-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":{"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}},"defines":{"DEPTH_PACKING":3200},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":true,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"lineBasicBuilder_OPTIMISED":{"type":"lineBasicBuilder","nodes":{"add1":{"type":"add","params":{"add0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"add2":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"add0","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"add1","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"vec3"},{"name":"add1","type":"vec3"},{"name":"add2","type":"vec3"}],"out":[{"name":"sum","type":"vec3"}]}},"attribute2":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute3":{"type":"attribute","params":{"name":"ptn"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"attribute4":{"type":"attribute","params":{"name":"ptuv","type":1},"connection_points":{"in":[],"out":[{"name":"val","type":"vec2"}]}},"constant1":{"type":"constant","params":{"type":4,"color":[0.011764705882352941,0.10980392156862745,0.01568627450980392],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant2":{"type":"constant","params":{"type":4,"color":[0.25098039215686274,0.4392156862745098,0.06274509803921569],"asColor":true},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"constant4":{"type":"constant","params":{"float":0.15},"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.1},"destMax":{"type":"float","default_value":1,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"val","node":"attribute2","output":"val"}],"connection_points":{"in":[{"name":"val","type":"float"},{"name":"destMin","type":"float"},{"name":"destMax","type":"float"}],"out":[{"name":"val","type":"float"}]}},"floatToInt1":{"type":"floatToInt","params":{"float":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"float","node":"multAdd1","output":"val"}]},"floatToVec3_1":{"type":"floatToVec3","params":{"x":{"overriden_options":{}},"y":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"x","node":"constant4","output":"val"},{"index":1,"inputName":"y","node":"constant4","output":"val"},{"index":2,"inputName":"z","node":"constant4","output":"val"}]},"globals1":{"type":"globals"},"globals2":{"type":"globals"},"instanceTransform1":{"type":"instanceTransform","params":{"position":{"overriden_options":{}},"normal":{"overriden_options":{}},"instancePosition":{"overriden_options":{}},"instanceQuaternion":{"overriden_options":{}},"instanceScale":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"position","node":"multScalar1","output":"val"}]},"mix1":{"type":"mix","params":{"value0":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"value1":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"blend":{"type":"float","default_value":0.5,"options":{"spare":true,"editable":false},"raw_input":0.65}},"inputs":[{"index":0,"inputName":"value0","node":"constant1","output":"val"},{"index":1,"inputName":"value1","node":"constant2","output":"val"},{"index":2,"inputName":"blend","node":"fitFrom01_1","output":"val"}],"connection_points":{"in":[{"name":"value0","type":"vec3"},{"name":"value1","type":"vec3"},{"name":"blend","type":"float"}],"out":[{"name":"mix","type":"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":4},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"attribute3","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"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":false}},"preAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true},"raw_input":[-0.5,-0.5,-0.5]},"mult":{"type":"vector3","default_value":[1,1,1],"options":{"spare":true,"editable":false},"raw_input":[2,2,2]},"postAdd":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"inputName":"value","node":"vec4ToVec3_1","output":"vec3"},null,{"index":2,"inputName":"mult","node":"floatToVec3_1","output":"vec3"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"preAdd","type":"vec3"},{"name":"mult","type":"vec3"},{"name":"postAdd","type":"vec3"}],"out":[{"name":"val","type":"vec3"}]}},"multAdd3":{"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},"raw_input":-0.5},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":2},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":1.6}},"inputs":[{"index":0,"inputName":"value","node":"vec4ToVec3_1","output":"w"}],"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":false}}},"inputs":[{"index":0,"inputName":"value","node":"globals2","output":"position"},{"index":1,"inputName":"mult","node":"multAdd3","output":"val"}],"connection_points":{"in":[{"name":"value","type":"vec3"},{"name":"mult","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"add1","output":"sum"},{"index":1,"inputName":"color","node":"mix1","output":"mix"}]},"texture2DArray1":{"type":"texture2DArray","params":{"uv":{"overriden_options":{}},"layer":{"raw_input":1,"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"attribute4","output":"val"},{"index":1,"inputName":"layer","node":"floatToInt1","output":"int"}]},"vec2ToVec3_1":{"type":"vec2ToVec3","params":{"vec2":{"overriden_options":{}},"z":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec2","node":"attribute4","output":"val"},{"index":1,"inputName":"z","node":"multAdd1","output":"val"}]},"vec4ToVec3_1":{"type":"vec4ToVec3","params":{"vec4":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec4","node":"texture2DArray1","output":"rgba"}]}},"params":{"linewidth":6.5,"texture3D1":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../../COP/builder2DArray1","overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-main","type":"LineBasicMaterial","color":16777215,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"linewidth":6.5},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDistanceMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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},"referencePosition":{"type":"v3","value":[0,0,0]},"nearDistance":{"value":1},"farDistance":{"value":1000}},"defines":{"USE_SIZEATTENUATION":1,"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","fragmentShader":"\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#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\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","lights":false,"clipping":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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}},"defines":{"DEPTH_PACKING":3201},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/grass/MAT/lineBasicBuilder_OPTIMISED-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":{"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}},"defines":{"DEPTH_PACKING":3200},"vertexShader":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\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":[{"type":"node_path","name":"texture3D1","defaultValue":"","uniformName":"v_POLY_texture_texture3D1"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}},"meshBasic_GROUND":{"type":"meshBasic","params":{"color":[0.06274509803921569,0.20392156862745098,0.03529411764705882]}}}},"attribId1":{"type":"attribId","params":{"id":false,"idName":"pt","idnName":"ptn"},"inputs":["line1"]},"attribRename1":{"type":"attribRename","params":{"oldName":"uv","newName":"ptuv"},"inputs":["scatter1"]},"instance1":{"type":"instance","params":{"attributesToCopy":"instance* id* ptn ptuv","material":"../MAT/lineBasicBuilder_OPTIMISED"},"inputs":["attribId1","attribRename1"],"flags":{"display":true}},"instance2":{"type":"instance","params":{"attributesToCopy":"instance* id* ptn ptuv","material":"../MAT/lineBasicBuilder_NON_OPTIMISED"},"inputs":["attribId1","attribRename1"]},"line1":{"type":"line","params":{"pointsCount":5,"direction":[0,0,1]}},"scatter1":{"type":"scatter","params":{"pointsCount":200000,"transferAttributes":true,"attributesToTransfer":"uv"},"inputs":["objectMerge1"]},"objectMerge1":{"type":"objectMerge","params":{"geometry":"../../ground/OUT"}}},"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}},"sky":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"sky1":{"type":"sky"}}},"material1":{"type":"material","params":{"material":"../MAT/sky1"},"inputs":["sphere1"],"flags":{"display":true}},"sphere1":{"type":"sphere","params":{"radius":1000}}},"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}},"ground":{"type":"geo","nodes":{"BVH1":{"type":"BVH","inputs":["OUT"]},"MAT":{"type":"materialsNetwork","nodes":{"meshBasic_GROUND":{"type":"meshBasic","params":{"color":[0.06274509803921569,0.20392156862745098,0.03529411764705882]}},"meshLambert_GROUND":{"type":"meshLambert","params":{"color":[0.010960094003125918,0.11443537381770343,0.011612245176281512]}}}},"OUT":{"type":"null","inputs":["transform1"]},"material1":{"type":"material","params":{"material":"../MAT/meshLambert_GROUND"},"inputs":["OUT"]},"noise1":{"type":"noise","params":{"amplitude":4.9,"freq":[-0.0060000000000000366,-0.0060000000000000366,-0.0060000000000000366],"offset":[0,0,26.7],"ampAttenuation":0.1,"freqIncrease":0.3,"seed":16,"useNormals":true},"inputs":["plane1"]},"plane1":{"type":"plane","params":{"size":[200,300],"stepSize":1.2,"center":[14.651343247698263,-7.775128346119189,0]}},"transform1":{"type":"transform","params":{"t":[0,2.9124666555513055,0]},"inputs":["noise1"]},"oceanPlane1":{"type":"oceanPlane","params":{"size":66},"inputs":["plane2"]},"plane2":{"type":"plane","params":{"size":[661,666],"useSegmentsCount":1,"stepSize":2,"center":[0,-11.3,0]}},"merge1":{"type":"merge","inputs":["oceanPlane1","material1"],"flags":{"display":true}}},"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":{"maxDistance":260,"target":[-33.62544586106904,-65.67812610218134,24.271132065270567]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera_DEFAULT"]},"cameraControls2":{"type":"cameraControls","nodes":{"firstPersonControls1":{"type":"firstPersonControls","params":{"colliderObject":"../../../ground/BVH1","capsuleHeight":2.3,"translateSpeed":2.8,"jumpStrength":33,"runSpeedMult":3.5,"startPosition":[2,8,2]}}},"params":{"node":"firstPersonControls1"},"inputs":["perspectiveCamera_FPS"]},"merge1":{"type":"merge","inputs":["cameraControls1","cameraControls2"],"flags":{"display":true}},"perspectiveCamera_DEFAULT":{"type":"perspectiveCamera","params":{"near":1,"far":1240,"position":[-128.19489384666974,59.37049813773632,170.28509739593437],"rotation":[-40.577241862378756,-26.193755021302916,-20.708017447225334]}},"perspectiveCamera_FPS":{"type":"perspectiveCamera"}},"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}},"lights":{"type":"geo","nodes":{"ambientLight1":{"type":"ambientLight","params":{"intensity":0.2}},"hemisphereLight1":{"type":"hemisphereLight"},"merge1":{"type":"merge","inputs":["ambientLight1","hemisphereLight1"],"flags":{"display":true}}},"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":{"mainCameraPath":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT"}},"ui":{"nodes":{"grid":{"pos":[50,-250],"nodes":{"planeHelper1":{"pos":[0,0]}}},"COP":{"pos":[-150,350],"nodes":{"builder2DArray1":{"pos":[-100,400],"nodes":{"add1":{"pos":[550,250]},"add2":{"pos":[150,400]},"constant1":{"pos":[-300,300]},"floatToVec3_1":{"pos":[-450,750]},"floatToVec3_2":{"pos":[-450,500]},"floatToVec3_3":{"pos":[-450,350]},"floatToVec3_4":{"pos":[-200,300]},"globals1":{"pos":[-1000,300]},"multAdd1":{"pos":[-550,500]},"multAdd2":{"pos":[-550,350]},"multAdd3":{"pos":[-700,200]},"multAdd4":{"pos":[550,500]},"multAdd5":{"pos":[450,700]},"multScalar1":{"pos":[-50,750]},"multScalar2":{"pos":[-300,600]},"noise1":{"pos":[300,500]},"noise2":{"pos":[-50,400]},"noise3":{"pos":[300,700]},"null1":{"pos":[-550,750]},"null2":{"pos":[-200,200]},"null3":{"pos":[-750,350]},"output1":{"pos":[700,500]},"vec2ToVec3_1":{"pos":[-550,100]}}},"envMap":{"pos":[50,200]},"imageEnv":{"pos":[50,100]},"imageUv":{"pos":[-100,100]}}},"grass":{"pos":[50,150],"nodes":{"MAT":{"pos":[-450,500],"nodes":{"lineBasicBuilder_NON_OPTIMISED":{"pos":[0,100],"nodes":{"attribute1":{"pos":[-800,700]},"attribute2":{"pos":[-750,500]},"constant1":{"pos":[-750,300]},"constant2":{"pos":[-750,400]},"constant3":{"pos":[-450,550]},"fitFrom01_1":{"pos":[-600,500]},"instanceTransform1":{"pos":[-350,-100]},"mix1":{"pos":[-350,350]},"mix2":{"pos":[-250,450]},"noise1":{"pos":[-650,700]},"output1":{"pos":[500,150]},"smoothstep1":{"pos":[-450,700]},"subnet_length_variation":{"pos":[-550,-100],"nodes":{"attribute3":{"pos":[-1550,-50]},"floatToVec3_3":{"pos":[-1300,-50]},"globals1":{"pos":[-1500,-350]},"length1":{"pos":[-900,-150]},"multAdd2":{"pos":[-1050,-50]},"multScalar2":{"pos":[-800,-300]},"noise2":{"pos":[-1150,-50]},"subnetOutput1":{"pos":[-600,-300]},"vec3ToFloat1":{"pos":[-1400,-50]}}},"subnet_noise":{"pos":[-150,-100],"nodes":{"add1":{"pos":[-200,-150]},"add2":{"pos":[-800,-350]},"attribute1":{"pos":[-1150,350]},"floatToVec3_1":{"pos":[-900,200]},"floatToVec3_2":{"pos":[-1100,-50]},"floatToVec3_3":{"pos":[-1050,-200]},"globals2":{"pos":[-1350,-150]},"multAdd1":{"pos":[-1200,-50]},"multAdd2":{"pos":[-1150,-200]},"multScalar1":{"pos":[-700,200]},"multScalar2":{"pos":[-850,50]},"noise1":{"pos":[-350,-50]},"noise2":{"pos":[-900,-300]},"null1":{"pos":[-1000,200]},"subnetInput1":{"pos":[-1100,-300]},"subnetOutput1":{"pos":[0,-200]}}},"varyingRead1":{"pos":[250,350]},"varyingWrite1":{"pos":[-150,450],"comment":"using the varyingWrite/varyingRead instead of setting the color directly allows us to set the color in the vertex shader, as opposed to the fragment shader, which would be less performant."}}},"lineBasicBuilder_OPTIMISED":{"pos":[0,0],"nodes":{"add1":{"pos":[350,-400]},"attribute2":{"pos":[-750,500]},"attribute3":{"pos":[-800,-50]},"attribute4":{"pos":[-800,-200]},"constant1":{"pos":[-750,300]},"constant2":{"pos":[-750,400]},"constant4":{"pos":[-350,0]},"fitFrom01_1":{"pos":[-600,500]},"floatToInt1":{"pos":[-550,-50]},"floatToVec3_1":{"pos":[-250,0]},"globals1":{"pos":[-900,-200]},"globals2":{"pos":[-550,-550]},"instanceTransform1":{"pos":[150,-600]},"mix1":{"pos":[-350,350]},"multAdd1":{"pos":[-650,-50]},"multAdd2":{"pos":[-100,-200]},"multAdd3":{"pos":[-200,-450]},"multScalar1":{"pos":[-100,-550]},"output1":{"pos":[650,0]},"texture2DArray1":{"pos":[-400,-200]},"vec2ToVec3_1":{"pos":[-550,-150]},"vec4ToVec3_1":{"pos":[-250,-200]}}},"meshBasic_GROUND":{"pos":[0,250]}}},"attribId1":{"pos":[-350,300]},"attribRename1":{"pos":[-100,400]},"instance1":{"pos":[-350,650],"comment":"this demo includes 2 different shaders for the grass. the one currently displayed is optimised, as it reads the noise from a 3D texture. But that comes at a visual cost, as there is less variation in that noise."},"instance2":{"pos":[100,600],"comment":"If you set the display flag on that node, you can see the less optimised, but nicer grass. It is less optimised as the noise is calculated for every vertex, and not inside a texture. But that allows nicer variation."},"line1":{"pos":[-350,100]},"scatter1":{"pos":[50,200]},"objectMerge1":{"pos":[-50,50]}}},"sky":{"pos":[50,-350],"nodes":{"MAT":{"pos":[-350,350],"nodes":{"sky1":{"pos":[-50,100]}}},"material1":{"pos":[-150,350],"comment":"here we assign the sky material to the sphere"},"sphere1":{"pos":[-150,-100],"comment":"in order to have a sky that always appears to be far enough, we set the radius of the sphere to a large value, like 1000 in this case.\\n\\nThe material is set with depthWrite=false, so the far plane of the camera can remain closer than the radius."}}},"ground":{"pos":[50,-150],"comment":"the changes here are:\\n- replaced the meshBasic material by the meshLambert, as the meshBasic does not react to light\\n- merged the oceanPlane with the ground, and make the plane larger than the grass\\n- increased the size of the oceanPlane","selection":["oceanPlane1"],"nodes":{"BVH1":{"pos":[250,450]},"MAT":{"pos":[-650,550],"selection":["meshLambert_GROUND"],"nodes":{"meshBasic_GROUND":{"pos":[0,200]},"meshLambert_GROUND":{"pos":[0,350]}}},"OUT":{"pos":[0,300]},"material1":{"pos":[0,450]},"noise1":{"pos":[0,50]},"plane1":{"pos":[0,-100]},"transform1":{"pos":[0,150]},"oceanPlane1":{"pos":[-400,200]},"plane2":{"pos":[-400,50]},"merge1":{"pos":[-250,650]}}},"cameras":{"pos":[50,250],"comment":"For the camera, since the environment is quite large, I've increased the far plane, as well as increased the max distance of the camera controls","nodes":{"cameraControls1":{"pos":[-250,0],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"cameraControls2":{"pos":[100,0],"nodes":{"firstPersonControls1":{"pos":[-50,100]}}},"merge1":{"pos":[-50,250]},"perspectiveCamera_DEFAULT":{"pos":[-250,-150]},"perspectiveCamera_FPS":{"pos":[100,-150]}}},"lights":{"pos":[50,450],"comment":"I've set the lights in here for better organisation","nodes":{"ambientLight1":{"pos":[-150,-50]},"hemisphereLight1":{"pos":[150,0]},"merge1":{"pos":[0,200]}}}}},"shaders":{"/COP/builder2DArray1":{"fragment":"#include <common>\n\nuniform float uLayer;\nuniform vec2 resolution;\n\n// removed:\n//// INSERT DEFINE\n\n\n\n// /COP/builder2DArray1/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_COP_builder2DArray1_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /COP/builder2DArray1/noise1\n\nfloat fbm_snoise_COP_builder2DArray1_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /COP/builder2DArray1/noise3\n\nfloat fbm_snoise_COP_builder2DArray1_noise3(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /COP/builder2DArray1/globals1\nuniform float time;\n\n\n\n\n\nvoid main() {\n\n\tvec4 diffuseColor = vec4(0.0,0.0,0.0,1.0);\n\n\n// removed:\n//\t// INSERT BODY\n\n\n\n\t// /COP/builder2DArray1/globals1\n\tfloat v_POLY_globals1_layer = uLayer;\n\tfloat v_POLY_globals1_time = time;\n\tvec2 v_POLY_globals1_uv = vec2(gl_FragCoord.x / (resolution.x-1.), gl_FragCoord.y / (resolution.y-1.));\n\t\n\t// /COP/builder2DArray1/constant1\n\tfloat v_POLY_constant1_val = 0.0;\n\t\n\t// /COP/builder2DArray1/null1\n\tfloat v_POLY_null1_val = v_POLY_globals1_layer;\n\t\n\t// /COP/builder2DArray1/multAdd3\n\tfloat v_POLY_multAdd3_val = (0.42*(v_POLY_globals1_layer + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/null3\n\tfloat v_POLY_null3_val = v_POLY_globals1_time;\n\t\n\t// /COP/builder2DArray1/floatToVec3_4\n\tvec3 v_POLY_floatToVec3_4_vec3 = vec3(v_POLY_constant1_val, v_POLY_constant1_val, v_POLY_constant1_val);\n\t\n\t// /COP/builder2DArray1/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_null1_val, v_POLY_null1_val, v_POLY_null1_val);\n\t\n\t// /COP/builder2DArray1/vec2ToVec3_1\n\tvec3 v_POLY_vec2ToVec3_1_vec3 = vec3(v_POLY_globals1_uv.xy, v_POLY_multAdd3_val);\n\t\n\t// /COP/builder2DArray1/multAdd2\n\tfloat v_POLY_multAdd2_val = (-0.1*(v_POLY_null3_val + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/multAdd1\n\tfloat v_POLY_multAdd1_val = (0.2*(v_POLY_null3_val + 0.0)) + 0.0;\n\t\n\t// /COP/builder2DArray1/multScalar1\n\tvec3 v_POLY_multScalar1_val = (0.55*v_POLY_floatToVec3_1_vec3);\n\t\n\t// /COP/builder2DArray1/null2\n\tvec3 v_POLY_null2_val = v_POLY_vec2ToVec3_1_vec3;\n\t\n\t// /COP/builder2DArray1/floatToVec3_3\n\tvec3 v_POLY_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_multAdd2_val);\n\t\n\t// /COP/builder2DArray1/floatToVec3_2\n\tvec3 v_POLY_floatToVec3_2_vec3 = vec3(v_POLY_multAdd1_val, 0.0, 0.0);\n\t\n\t// /COP/builder2DArray1/noise2\n\tfloat v_POLY_noise2_noisex = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\tfloat v_POLY_noise2_noisey = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\tfloat v_POLY_noise2_noisez = (v_POLY_floatToVec3_4_vec3*fbm_snoise_COP_builder2DArray1_noise2((v_POLY_null2_val*vec3(2.7, 1.0, 2.7))+(v_POLY_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\tvec3 v_POLY_noise2_noise = vec3(v_POLY_noise2_noisex, v_POLY_noise2_noisey, v_POLY_noise2_noisez);\n\t\n\t// /COP/builder2DArray1/add2\n\tvec3 v_POLY_add2_sum = (v_POLY_null2_val + v_POLY_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t// /COP/builder2DArray1/noise1\n\tfloat v_POLY_noise1_noisex = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\tfloat v_POLY_noise1_noisey = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\tfloat v_POLY_noise1_noisez = (v_POLY_multScalar1_val*fbm_snoise_COP_builder2DArray1_noise1((v_POLY_add2_sum*vec3(10.0, 0.01, 10.0))+(v_POLY_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\tvec3 v_POLY_noise1_noise = vec3(v_POLY_noise1_noisex, v_POLY_noise1_noisey, v_POLY_noise1_noisez);\n\t\n\t// /COP/builder2DArray1/noise3\n\tfloat v_POLY_noise3_noise = 0.42*fbm_snoise_COP_builder2DArray1_noise3((v_POLY_add2_sum*vec3(100.0, 100.0, 100.0))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /COP/builder2DArray1/multAdd4\n\tvec3 v_POLY_multAdd4_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_noise1_noise + vec3(0.0, 0.0, 0.0))) + vec3(0.5, 0.5, 0.5);\n\t\n\t// /COP/builder2DArray1/multAdd5\n\tfloat v_POLY_multAdd5_val = (1.0*(v_POLY_noise3_noise + 0.0)) + 0.5;\n\t\n\t// /COP/builder2DArray1/output1\n\tdiffuseColor.xyz = v_POLY_multAdd4_val;\n\tdiffuseColor.a = v_POLY_multAdd5_val;\n\n\n\n\n\tgl_FragColor = vec4( diffuseColor );\n}"},"/grass/MAT/lineBasicBuilder_NON_OPTIMISED":{"vertex":"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n#include <uv_pars_vertex>\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>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_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\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\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 <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\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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","customDepthMaterial.vertex":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n// Modulo 289 without a division (only multiplications)\nfloat mod289(float x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec2 mod289(vec2 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec3 mod289(vec3 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\nvec4 mod289(vec4 x) {\n return x - floor(x * (1.0 / 289.0)) * 289.0;\n}\n// Modulo 7 without a division\nvec3 mod7(vec3 x) {\n return x - floor(x * (1.0 / 7.0)) * 7.0;\n}\n\n// Permutation polynomial: (34x^2 + x) mod 289\nfloat permute(float x) {\n return mod289(((x*34.0)+1.0)*x);\n}\nvec3 permute(vec3 x) {\n return mod289((34.0 * x + 1.0) * x);\n}\nvec4 permute(vec4 x) {\n return mod289(((x*34.0)+1.0)*x);\n}\n\nfloat taylorInvSqrt(float r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\nvec4 taylorInvSqrt(vec4 r)\n{\n return 1.79284291400159 - 0.85373472095314 * r;\n}\n\nvec2 fade(vec2 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec3 fade(vec3 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\nvec4 fade(vec4 t) {\n return t*t*t*(t*(t*6.0-15.0)+10.0);\n}\n//\n// Description : Array and textureless GLSL 2D/3D/4D simplex \n// noise functions.\n// Author : Ian McEwan, Ashima Arts.\n// Maintainer : stegu\n// Lastmod : 20110822 (ijm)\n// License : Copyright (C) 2011 Ashima Arts. All rights reserved.\n// Distributed under the MIT License. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n// https://github.com/stegu/webgl-noise\n// \n\n\n\nfloat snoise(vec3 v)\n { \n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n// First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n// Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n// Permutations\n i = mod289(i); \n vec4 p = permute( permute( permute( \n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) \n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n// Gradients: 7x7 points over a square, mapped onto an octahedron.\n// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n//Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n// Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), \n dot(p2,x2), dot(p3,x3) ) );\n }\n\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\nfloat fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1(in vec3 st) {\n\tfloat value = 0.0;\n\tfloat amplitude = 1.0;\n\tfor (int i = 0; i < 3; i++) {\n\t\tvalue += amplitude * snoise(st);\n\t\tst *= 2.0;\n\t\tamplitude *= 0.5;\n\t}\n\treturn value;\n}\n\n\n\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nattribute vec3 instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation\n\tvec3 v_POLY_subnet_length_variation_input0 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\n\t\tv_POLY_subnet_length_variation_globals1_position = vec3(position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\n\t\tvec3 v_POLY_subnet_length_variation_attribute3_val = instancePosition;\n\t\tv_POLY_attribute_instancePosition = vec3(instancePosition);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/vec3ToFloat1\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_x = v_POLY_subnet_length_variation_attribute3_val.x;\n\t\tfloat v_POLY_subnet_length_variation_vec3ToFloat1_z = v_POLY_subnet_length_variation_attribute3_val.z;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/floatToVec3_3\n\t\tvec3 v_POLY_subnet_length_variation_floatToVec3_3_vec3 = vec3(v_POLY_subnet_length_variation_vec3ToFloat1_x, 0.0, v_POLY_subnet_length_variation_vec3ToFloat1_z);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/noise2\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisex = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisey = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_length_variation_noise2_noisez = (vec3(1.0, 1.0, 1.0)*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_length_variation_noise2((v_POLY_subnet_length_variation_floatToVec3_3_vec3*vec3(0.5, 0.5, 0.5))+(vec3(0.0, 3.2, 0.0)+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_length_variation_noise2_noise = vec3(v_POLY_subnet_length_variation_noise2_noisex, v_POLY_subnet_length_variation_noise2_noisey, v_POLY_subnet_length_variation_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multAdd2\n\t\tvec3 v_POLY_subnet_length_variation_multAdd2_val = (vec3(0.5, 0.5, 0.5)*(v_POLY_subnet_length_variation_noise2_noise + vec3(0.0, 0.0, 0.0))) + vec3(1.0, 1.0, 1.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/length1\n\t\tfloat v_POLY_subnet_length_variation_length1_val = length(v_POLY_subnet_length_variation_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/multScalar2\n\t\tvec3 v_POLY_subnet_length_variation_multScalar2_val = (v_POLY_subnet_length_variation_length1_val*v_POLY_subnet_length_variation_globals1_position);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/subnetOutput1\n\t\tv_POLY_subnet_length_variation_input0 = v_POLY_subnet_length_variation_multScalar2_val;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.4392156862745098, 0.4235294117647059, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/attribute1\n\tvec3 v_POLY_attribute1_val = instancePosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_subnet_length_variation_input0);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/noise1\n\tfloat v_POLY_noise1_noise = 1.0*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_noise1((v_POLY_attribute1_val*vec3(0.6, 0.6, 0.6))+vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise\n\tvec3 v_POLY_subnet_noise_input0 = v_POLY_instanceTransform1_position;\n\tvec3 v_POLY_subnet_noise_input1 = vec3(0.0, 0.0, 0.0);\n\tvec3 v_POLY_subnet_noise_input2 = vec3(0.0, 0.0, 0.0);\n\tif(true){\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetInput1\n\t\tvec3 v_POLY_subnet_noise_subnetInput1_input0 = v_POLY_instanceTransform1_position;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\n\t\tfloat v_POLY_subnet_noise_attribute1_val = ptn;\n\t\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\n\t\tfloat v_POLY_subnet_noise_globals2_time = time;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/null1\n\t\tfloat v_POLY_subnet_noise_null1_val = v_POLY_subnet_noise_attribute1_val;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd2\n\t\tfloat v_POLY_subnet_noise_multAdd2_val = (-0.1*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multAdd1\n\t\tfloat v_POLY_subnet_noise_multAdd1_val = (0.2*(v_POLY_subnet_noise_globals2_time + 0.0)) + 0.0;\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_1\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_1_vec3 = vec3(v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val, v_POLY_subnet_noise_null1_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_3\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_3_vec3 = vec3(0.0, 0.0, v_POLY_subnet_noise_multAdd2_val);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/floatToVec3_2\n\t\tvec3 v_POLY_subnet_noise_floatToVec3_2_vec3 = vec3(v_POLY_subnet_noise_multAdd1_val, 0.0, 0.0);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar1\n\t\tvec3 v_POLY_subnet_noise_multScalar1_val = (0.55*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/multScalar2\n\t\tvec3 v_POLY_subnet_noise_multScalar2_val = (0.19*v_POLY_subnet_noise_floatToVec3_1_vec3);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise2\n\t\tfloat v_POLY_subnet_noise_noise2_noisex = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise2_noisey = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise2_noisez = (v_POLY_subnet_noise_multScalar2_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise2((v_POLY_subnet_noise_subnetInput1_input0*vec3(0.19999999999999996, 0.19999999999999996, 0.19999999999999996))+(v_POLY_subnet_noise_floatToVec3_3_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise2_noise = vec3(v_POLY_subnet_noise_noise2_noisex, v_POLY_subnet_noise_noise2_noisey, v_POLY_subnet_noise_noise2_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add2\n\t\tvec3 v_POLY_subnet_noise_add2_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise2_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/noise1\n\t\tfloat v_POLY_subnet_noise_noise1_noisex = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(0.0, 0.0, 0.0)))).x;\n\t\tfloat v_POLY_subnet_noise_noise1_noisey = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(1000.0, 1000.0, 1000.0)))).y;\n\t\tfloat v_POLY_subnet_noise_noise1_noisez = (v_POLY_subnet_noise_multScalar1_val*fbm_snoise_grass_MAT_lineBasicBuilder_NON_OPTIMISED_subnet_noise_noise1((v_POLY_subnet_noise_add2_sum*vec3(0.7, 0.1, 0.7))+(v_POLY_subnet_noise_floatToVec3_2_vec3+vec3(2000.0, 2000.0, 2000.0)))).z;\n\t\tvec3 v_POLY_subnet_noise_noise1_noise = vec3(v_POLY_subnet_noise_noise1_noisex, v_POLY_subnet_noise_noise1_noisey, v_POLY_subnet_noise_noise1_noisez);\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/add1\n\t\tvec3 v_POLY_subnet_noise_add1_sum = (v_POLY_subnet_noise_subnetInput1_input0 + v_POLY_subnet_noise_noise1_noise + vec3(0.0, 0.0, 0.0));\n\t\n\t\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/subnetOutput1\n\t\tv_POLY_subnet_noise_input0 = v_POLY_subnet_noise_add1_sum;\n\t}\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(0.71, 0.86, v_POLY_noise1_noise);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tvec3 transformed = v_POLY_subnet_noise_input0;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/mix2\n\tvec3 v_POLY_mix2_mix = mix(v_POLY_mix1_mix, v_POLY_constant3_val, v_POLY_smoothstep1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingWrite1\n\tbasecolor = v_POLY_mix2_mix;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/globals2\nuniform float time;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/globals1\nvarying vec3 v_POLY_subnet_length_variation_globals1_position;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_length_variation/attribute3\nvarying vec3 v_POLY_attribute_instancePosition;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\nvarying vec3 basecolor;\n\n// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/subnet_noise/attribute1\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/varyingRead1\n\tvec3 v_POLY_varyingRead1_fragment = basecolor;\n\t\n\t// /grass/MAT/lineBasicBuilder_NON_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_varyingRead1_fragment;\n\n\n\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"},"/grass/MAT/lineBasicBuilder_OPTIMISED":{"vertex":"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n#include <uv_pars_vertex>\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>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\t#include <morphcolor_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_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\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#define DISTANCE\nvarying vec3 vWorldPosition;\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\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 <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\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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","customDepthMaterial.vertex":"\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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 scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n\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\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nprecision highp sampler2DArray;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\nuniform sampler2DArray v_POLY_texture_texture3D1;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\nvarying vec3 v_POLY_globals2_position;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\nattribute vec2 ptuv;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\nattribute float ptn;\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n\n\n\n\n\n// vHighPrecisionZW is added to match CustomMeshDepth.frag\n// which is itself taken from threejs\nvarying vec2 vHighPrecisionZW;\n\n\nvoid main() {\n\n\t// INSERT BODY\n\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/globals2\n\tv_POLY_globals2_position = vec3(position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute4\n\tvec2 v_POLY_attribute4_val = ptuv;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute3\n\tfloat v_POLY_attribute3_val = ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant4\n\tfloat v_POLY_constant4_val = 0.15;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tv_POLY_attribute_ptn = float(ptn);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd1\n\tfloat v_POLY_multAdd1_val = (4.0*(v_POLY_attribute3_val + 0.0)) + 0.0;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToVec3_1\n\tvec3 v_POLY_floatToVec3_1_vec3 = vec3(v_POLY_constant4_val, v_POLY_constant4_val, v_POLY_constant4_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_multAdd1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/texture2DArray1\n\tvec4 v_POLY_texture2DArray1_rgba = texture(v_POLY_texture_texture3D1, vec3(v_POLY_attribute4_val,v_POLY_floatToInt1_int));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_texture2DArray1_rgba.xyz;\n\tfloat v_POLY_vec4ToVec3_1_w = v_POLY_texture2DArray1_rgba.w;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd3\n\tfloat v_POLY_multAdd3_val = (2.0*(v_POLY_vec4ToVec3_1_w + -0.5)) + 1.6;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multAdd2\n\tvec3 v_POLY_multAdd2_val = (v_POLY_floatToVec3_1_vec3*(v_POLY_vec4ToVec3_1_vec3 + vec3(-0.5, -0.5, -0.5))) + vec3(0.0, 0.0, 0.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/multScalar1\n\tvec3 v_POLY_multScalar1_val = (v_POLY_multAdd3_val*v_POLY_globals2_position);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(v_POLY_multScalar1_val);\n\tv_POLY_instanceTransform1_position *= instanceScale;\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// /grass/MAT/lineBasicBuilder_OPTIMISED/add1\n\tvec3 v_POLY_add1_sum = (v_POLY_instanceTransform1_position + v_POLY_multAdd2_val + vec3(0.0, 0.0, 0.0));\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tvec3 transformed = v_POLY_add1_sum;vec4 mvPosition = vec4( transformed, 1.0 ); gl_Position = projectionMatrix * modelViewMatrix * mvPosition;\n\n\n\n\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include <color_vertex>\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n// removed:\n//\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\n\n\tvHighPrecisionZW = gl_Position.zw;\n}\n","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/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\n\n\n\n\n\n// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\nvarying float v_POLY_attribute_ptn;\n\n\n\n\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\n\n\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant1\n\tvec3 v_POLY_constant1_val = vec3(0.011764705882352941, 0.10980392156862745, 0.01568627450980392);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.25098039215686274, 0.4392156862745098, 0.06274509803921569);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/attribute2\n\tfloat v_POLY_attribute2_val = v_POLY_attribute_ptn;\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/fitFrom01_1\n\tfloat v_POLY_fitFrom01_1_val = fitFrom01(v_POLY_attribute2_val, -0.1, 1.0);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/mix1\n\tvec3 v_POLY_mix1_mix = mix(v_POLY_constant1_val, v_POLY_constant2_val, v_POLY_fitFrom01_1_val);\n\t\n\t// /grass/MAT/lineBasicBuilder_OPTIMISED/output1\n\tdiffuseColor.xyz = v_POLY_mix1_mix;\n\n\n\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"}},"jsFunctionBodies":{}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.6025492468134415,"split_panel0":{"panelTypes":["viewer","params","network"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/perspectiveCamera_DEFAULT","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false}}},"split_panel1":{"panelTypes":["viewer","params","network"],"currentPanelIndex":1,"panel_data":{"active_folder":2218,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["viewer","params","network"],"currentPanelIndex":2,"panel_data":{"camera":{"position":{"x":-121.50309703203713,"y":-118.12187259785398},"zoom":0.8785286562709399},"history":{"2":{"position":{"x":-121.50309703203713,"y":-118.12187259785398},"zoom":0.8785286562709399},"128":{"position":{"x":32.92599803895985,"y":-352.77896810911204},"zoom":0.8785286562709399},"272":{"position":{"x":139.83803624067164,"y":-393.8531007867804},"zoom":0.8505286562709399},"344":{"position":{"x":88.65920156883212,"y":-88.70107111169102},"zoom":0.8785286562709399},"596":{"position":{"x":107.13906558,"y":-565.8694901399999},"zoom":0.7620789513793633},"668":{"position":{"x":0,"y":-125},"zoom":0.7620789513793633},"2115":{"position":{"x":-84.23174300779809,"y":-256.9133398701339},"zoom":0.8785286562709399},"2281":{"position":{"x":-35.39402173913044,"y":-144.90489130434787},"zoom":1.1615286562709395},"2319":{"position":{"x":0,"y":0},"zoom":0.8785286562709399},"2484":{"position":{"x":9.106134379221416,"y":-43.25413830130172},"zoom":0.8785286562709399}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/","/grass","/grass","/grass","/grass","/grass","/grass","/grass"],"navigationHistory":{"nodePaths":{"1":["/ground","/","/grass","/","/ground","/","/grass","/","/ground","/","/cameras","/cameras/cameraControls1","/cameras","/","/ground","/","/cameras","/","/ground","/"],"2":["/grass"],"3":["/grass"],"4":["/grass"],"5":["/grass"],"6":["/grass"],"7":["/grass"],"8":["/grass"]},"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
cop/builder2DArray;cop/envMap;cop/image;cop/imageEXR;event/cameraOrbitControls;event/firstPersonControls;mat/lineBasicBuilder;mat/meshBasic;mat/meshLambert;mat/sky;obj/copNetwork;obj/geo;sop/BVH;sop/ambientLight;sop/attribId;sop/attribRename;sop/cameraControls;sop/hemisphereLight;sop/instance;sop/line;sop/material;sop/materialsNetwork;sop/merge;sop/noise;sop/null;sop/objectMerge;sop/oceanPlane;sop/perspectiveCamera;sop/plane;sop/planeHelper;sop/scatter;sop/sphere;sop/transform
Used operations
Used modules
Used assemblers
GL_LINE;GL_TEXTURE_2D_ARRAY
Used integrations
[]
Used assets
Nodes map
{"/grid":"obj/geo","/grid/planeHelper1":"sop/planeHelper","/COP":"obj/copNetwork","/COP/builder2DArray1":"cop/builder2DArray","/COP/envMap":"cop/envMap","/COP/imageEnv":"cop/imageEXR","/COP/imageUv":"cop/image","/grass":"obj/geo","/grass/MAT":"sop/materialsNetwork","/grass/MAT/lineBasicBuilder_NON_OPTIMISED":"mat/lineBasicBuilder","/grass/MAT/lineBasicBuilder_OPTIMISED":"mat/lineBasicBuilder","/grass/MAT/meshBasic_GROUND":"mat/meshBasic","/grass/attribId1":"sop/attribId","/grass/attribRename1":"sop/attribRename","/grass/instance1":"sop/instance","/grass/instance2":"sop/instance","/grass/line1":"sop/line","/grass/scatter1":"sop/scatter","/grass/objectMerge1":"sop/objectMerge","/sky":"obj/geo","/sky/MAT":"sop/materialsNetwork","/sky/MAT/sky1":"mat/sky","/sky/material1":"sop/material","/sky/sphere1":"sop/sphere","/ground":"obj/geo","/ground/BVH1":"sop/BVH","/ground/MAT":"sop/materialsNetwork","/ground/MAT/meshBasic_GROUND":"mat/meshBasic","/ground/MAT/meshLambert_GROUND":"mat/meshLambert","/ground/OUT":"sop/null","/ground/material1":"sop/material","/ground/noise1":"sop/noise","/ground/plane1":"sop/plane","/ground/transform1":"sop/transform","/ground/oceanPlane1":"sop/oceanPlane","/ground/plane2":"sop/plane","/ground/merge1":"sop/merge","/cameras":"obj/geo","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/cameraControls2":"sop/cameraControls","/cameras/cameraControls2/firstPersonControls1":"event/firstPersonControls","/cameras/merge1":"sop/merge","/cameras/perspectiveCamera_DEFAULT":"sop/perspectiveCamera","/cameras/perspectiveCamera_FPS":"sop/perspectiveCamera","/lights":"obj/geo","/lights/ambientLight1":"sop/ambientLight","/lights/hemisphereLight1":"sop/hemisphereLight","/lights/merge1":"sop/merge"}
Js version
Editor version
Engine version
Logout
0%
There was a problem displaying your scene:
view scene source