Name
*
Code
{"properties":{"frame":1769,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/perspectiveCamera1","versions":{"polygonjs":"1.1.262"}},"root":{"type":"root","nodes":{"hemisphereLight1":{"type":"hemisphereLight","flags":{"display":true}},"perspectiveCamera1":{"type":"perspectiveCamera","nodes":{"events1":{"type":"eventsNetwork","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[-0.32778130444084347,-0.192630758771347,-0.07727433770887207]}}},"selection":["cameraOrbitControls1"]}},"params":{"t":[3.0161526633531355,1.1787657307191874,2.814738208647524],"r":[-22.723127930556515,44.66532130223666,16.403892417511617],"controls":"./events1/cameraOrbitControls1"},"flags":{"display":true}},"COP":{"type":"copNetwork","nodes":{"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}},"envMap":{"type":"envMap","inputs":["imageEnv"]}}},"background_wall":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"meshStandard1":{"type":"meshStandard","params":{"metalness":0,"roughness":1}}}},"material1":{"type":"material","params":{"material":"../MAT/meshStandard1"},"inputs":["plane1"],"flags":{"display":true}},"plane1":{"type":"plane","params":{"size":[23,23],"direction":[0,0,1],"center":[0,0,-2.6]}}},"flags":{"display":true}},"lights":{"type":"geo","nodes":{"areaLight1":{"type":"areaLight","params":{"width":1.6,"showHelper":true}},"hemisphereLight1":{"type":"hemisphereLight"},"merge1":{"type":"merge","inputs":["polarTransform1","polarTransform2","hemisphereLight1"],"flags":{"display":true}},"polarTransform1":{"type":"polarTransform","params":{"longitude":64.8,"latitude":36,"depth":2.8},"inputs":["spotLight1"]},"polarTransform2":{"type":"polarTransform","params":{"longitude":295.2,"latitude":-72,"depth":2.5},"inputs":["areaLight1"]},"spotLight1":{"type":"spotLight","params":{"penumbra":0.76}}},"flags":{"display":true}},"metaball_volume":{"type":"geo","nodes":{"box1":{"type":"box","params":{"size":2,"sizes":[1.7,1.5,1.7]}},"material1":{"type":"material","params":{"material":"../MAT/volumeBuilder1"},"inputs":["box1"],"flags":{"display":true}},"MAT":{"type":"materialsNetwork","nodes":{"volumeBuilder1":{"type":"volumeBuilder","nodes":{"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[{"index":0,"node":"complement1","output":"val"}]},"SDFSphere1":{"type":"SDFSphere","params":{"position":{"overriden_options":{}},"center":{"overriden_options":{}},"radius":{"raw_input":0.4,"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"rotate1","output":"val"}]},"smoothstep1":{"type":"smoothstep","params":{"edge0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false},"raw_input":0.22},"edge1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false},"raw_input":0.25},"x":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"node":"constant1","output":"val"},{"index":1,"node":"add1","output":"sum"},{"index":2,"node":"SDFUnion1","output":"union"}],"connection_points":{"in":[{"name":"edge0","type":"float"},{"name":"edge1","type":"float"},{"name":"x","type":"float"}],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"node":"smoothstep1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"SDFSphere2":{"type":"SDFSphere","params":{"position":{"overriden_options":{}},"center":{"raw_input":[0.7,-0.8,0],"overriden_options":{}},"radius":{"raw_input":0.43,"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"param1","output":"val"}]},"SDFUnion1":{"type":"SDFUnion","params":{"sdf0":{"overriden_options":{}},"sdf1":{"overriden_options":{}},"smooth":{"raw_input":1,"overriden_options":{}},"smoothFactor":{"raw_input":0.31,"overriden_options":{}}},"inputs":[{"index":0,"node":"SDFUnion2","output":"union"},{"index":1,"node":"SDFSphere2","output":"float"}]},"constant1":{"type":"constant","params":{"float":0.02},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"add1":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.01}},"inputs":[{"index":0,"node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float"},{"name":"add1","type":"float"}],"out":[{"name":"sum","type":"float"}]}},"constant2":{"type":"constant","params":{"type":4,"vec3":[0,0,0.6]},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"rotate1":{"type":"rotate","params":{"vector":{"type":"vector3","default_value":[0,0,1],"options":{"spare":true,"editable":false}},"axis":{"type":"vector3","default_value":[0,1,0],"options":{"spare":true,"editable":true}},"angle":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":3,"inputs":[{"index":0,"node":"constant2","output":"val"},null,{"index":2,"node":"globals2","output":"time"}],"connection_points":{"in":[{"name":"vector","type":"vec3"},{"name":"axis","type":"vec3"},{"name":"angle","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"globals2":{"type":"globals"},"param1":{"type":"param","params":{"name":"cursor","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"SDFBox1":{"type":"SDFBox","params":{"position":{"overriden_options":{}},"center":{"overriden_options":{}},"size":{"raw_input":[0.32000000000000006,0.32000000000000006,0.32000000000000006],"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"rotate2","output":"val"}]},"constant3":{"type":"constant","params":{"type":4,"vec3":[0,0,0.6]},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"rotate2":{"type":"rotate","params":{"vector":{"type":"vector3","default_value":[0,0,1],"options":{"spare":true,"editable":false}},"axis":{"type":"vector3","default_value":[0,1,0],"options":{"spare":true,"editable":true},"raw_input":[1,0,0]},"angle":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":3,"inputs":[{"index":0,"node":"constant3","output":"val"},null,{"index":2,"node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"vector","type":"vec3"},{"name":"axis","type":"vec3"},{"name":"angle","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"globals3":{"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},"raw_input":6},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.33},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"node":"globals3","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"}]}},"SDFUnion2":{"type":"SDFUnion","params":{"sdf0":{"overriden_options":{}},"sdf1":{"overriden_options":{}},"smooth":{"raw_input":1,"overriden_options":{}},"smoothFactor":{"raw_input":0.23,"overriden_options":{}}},"inputs":[{"index":0,"node":"SDFSphere1","output":"float"},{"index":1,"node":"SDFBox1","output":"float"}]}},"params":{"color":[0.43529411764705883,0.5019607843137255,0.7647058823529411],"stepSize":0.12,"density":3.96,"shadowDensity":0.74,"lightDir":[0.7,0.8,-1],"cursor":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[5.5954644323425295,0.8462119493215142,0],"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/metaball_volume/MAT/volumeBuilder1-main","type":"ShaderMaterial","name":"/metaball_volume/MAT/volumeBuilder1","color":16777215,"transparent":true,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"glslVersion":null,"uniforms":{"u_Color":{"type":"c","value":7307459},"u_VolumeDensity":{"value":3.96},"u_ShadowDensity":{"value":0.74},"u_StepSize":{"value":0.12},"u_BoundingBoxMin":{"type":"v3","value":[-1.7000000476837158,-1.5,-1.7000000476837158]},"u_BoundingBoxMax":{"type":"v3","value":[1.7000000476837158,1.5,1.7000000476837158]},"u_DirectionalLightDirection":{"type":"v3","value":[0.7,0.8,-1]},"v_POLY_param_cursor":{"type":"v3","value":[5.5954644323425295,0.8462119493215142,0]},"time":{"value":29.483333333333334}},"vertexShader":"precision highp float;\nprecision highp int;\n\nvarying vec3 vPw;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n\n\n\n\nvoid main()\t{\n\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\n\n\n\n\tvPw = position;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}","fragmentShader":"precision highp float;\nprecision highp int;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 q = abs(p) - b;\n\treturn length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);\n}\n\n\nfloat opUnion( float d1, float d2 ) { return min(d1,d2); }\nfloat opSubtraction( float d1, float d2 ) { return max(-d1,d2); }\nfloat opIntersection( float d1, float d2 ) { return max(d1,d2); }\n\nfloat opSmoothUnion( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) - k*h*(1.0-h);\n}\n\nfloat opSmoothSubtraction( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );\n\treturn mix( d2, -d1, h ) + k*h*(1.0-h);\n}\n\nfloat opSmoothIntersection( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) + k*h*(1.0-h);\n}\n\n// /metaball_volume/MAT/volumeBuilder1/rotate1\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// /metaball_volume/MAT/volumeBuilder1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n// /metaball_volume/MAT/volumeBuilder1/param1\nuniform vec3 v_POLY_param_cursor;\n\n\n\n\n\n#define DIR_LIGHTS_COUNT 1\n#define MAX_STEPS_COUNT 4096\n\nuniform vec3 u_Color;\nuniform float u_VolumeDensity;\nuniform float u_ShadowDensity;\nuniform float u_StepSize;\nuniform vec3 u_BoundingBoxMin;\nuniform vec3 u_BoundingBoxMax;\n//const int u_PointsCount = 3;\n//uniform vec3 u_Points[3];\nuniform sampler2D u_Map;\n\n//const int u_DirectionalLightsCount = 1;\nuniform vec3 u_DirectionalLightDirection; //[DIR_LIGHTS_COUNT];\n\nvarying vec3 vPw;\n// varying vec3 vN;\n// varying vec2 vUV;\n//varying vec3 vPCameraSpace;\n// varying vec4 vCd;\n\nvec3 normalize_in_bbox(vec3 point){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn vec3(\n\t\t(point.x - min.x) / (max.x - min.x),\n\t\t(point.y - min.y) / (max.y - min.y),\n\t\t(point.z - min.z) / (max.z - min.z)\n\t);\n}\n\nbool is_inside_bbox(vec3 Pw){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn (\n\t\tPw.x > min.x &&\n\t\tPw.y > min.y &&\n\t\tPw.z > min.z &&\n\n\t\tPw.x < max.x &&\n\t\tPw.y < max.y &&\n\t\tPw.z < max.z\n\t\t);\n}\n\nfloat density_to_opacity(float density, float step_size){\n\tfloat curent_density = density;\n\tcurent_density = max(0.0, curent_density);\n\n\tfloat opacity = (1.0-exp(-curent_density * step_size));\n\treturn max(opacity,0.0);\n}\n\nfloat density_function(vec3 position_for_step){\n\tfloat density = 1.0;\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/constant1\n\tfloat v_POLY_constant1_val = 0.02;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals1\n\tvec3 v_POLY_globals1_position = position_for_step;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/add1\n\tfloat v_POLY_add1_sum = (v_POLY_constant1_val + 0.01);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n\tfloat v_POLY_SDFSphere2_float = sdSphere(v_POLY_globals1_position - v_POLY_param1_val, 0.43);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate1\n\tvec3 v_POLY_rotate1_val = rotateWithAxisAngle(v_POLY_constant2_val, vec3(0.0, 1.0, 0.0), v_POLY_globals2_time);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/multAdd1\n\tfloat v_POLY_multAdd1_val = (1.33*(v_POLY_globals3_time + 6.0)) + 0.0;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere1\n\tfloat v_POLY_SDFSphere1_float = sdSphere(v_POLY_globals1_position - v_POLY_rotate1_val, 0.4);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate2\n\tvec3 v_POLY_rotate2_val = rotateWithAxisAngle(v_POLY_constant3_val, vec3(1.0, 0.0, 0.0), v_POLY_multAdd1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFBox1\n\tfloat v_POLY_SDFBox1_float = sdBox(v_POLY_globals1_position - v_POLY_rotate2_val, vec3(0.32000000000000006, 0.32000000000000006, 0.32000000000000006));\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion2\n\tfloat v_POLY_SDFUnion2_union = opSmoothUnion(v_POLY_SDFSphere1_float, v_POLY_SDFBox1_float, 0.23);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion1\n\tfloat v_POLY_SDFUnion1_union = opSmoothUnion(v_POLY_SDFUnion2_union, v_POLY_SDFSphere2_float, 0.31);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(v_POLY_constant1_val, v_POLY_add1_sum, v_POLY_SDFUnion1_union);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_smoothstep1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/output1\n\tdensity *= v_POLY_complement1_val;\n\n\n\n\n\treturn density;\n}\n\nvec4 raymarch_light(vec3 ray_dir, vec3 start_pos){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos + step_vector*rand(start_pos.x*ray_dir.xy);\n\tfloat opacity = 0.0;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( is_inside_bbox(current_pos) ){\n\n\t\t\tfloat density = density_function(current_pos) * u_ShadowDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\t\t\tcurrent_pos += step_vector;\n\n\t\t}else{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvec3 light_color = vec3(1.0, 1.0, 1.0) * u_Color;\n\tlight_color *= (1.0-opacity);\n\treturn vec4(light_color, 1.0-opacity);\n}\n\nvec4 raymarch_bbox(vec3 start_pos, vec3 ray_dir){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos - step_vector*rand(ray_dir.xz);\n\tfloat opacity = 0.0;\n\tvec3 color = vec3(0.0, 0.0, 0.0);\n\tfloat steps_count = 0.0;\n\tbool was_inside_bbox = false;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( i==0 || is_inside_bbox(current_pos) ){\n\t\t\twas_inside_bbox = true;\n\n\t\t\tfloat density = density_function(current_pos) * u_VolumeDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\n\t\t\tvec4 light_color = vec4(0.0,0.0,0.0,1.0); //vec4(1.0,1.0,1.0,1.0);\n\t\t\t// vec3 directional_light_direction;\n\t\t\t// for ( int l = 0; l < DIR_LIGHTS_COUNT; l++ ) {\n\t\t\t// directional_light_direction = u_DirectionalLightsDirection[ l ];\n\t\t\tlight_color += raymarch_light(-u_DirectionalLightDirection, current_pos);\n\t\t\t// }\n\t\t\tfloat blend = 1.0-opacity;\n\t\t\tcolor = mix( color.xyz, light_color.xyz, vec3(blend, blend, blend) );\n\t\t\tsteps_count += 1.0;\n\n\t\t}else{\n\t\t\tif (was_inside_bbox) { break; }\n\t\t}\n\t\tcurrent_pos += step_vector;\n\t}\n\n\treturn vec4(color, opacity);\n\t// steps_count = steps_count / 5.0;\n\t// return vec4(vec3(steps_count, steps_count, steps_count), 1.0);\n}\n\nvoid main()\t{\n\n\tvec3 eye = normalize(vPw - cameraPosition);\n\t// we can start from the bbox, as we are front facing\n\tvec3 start_pos = vPw;\n\n\tvec4 color = raymarch_bbox(start_pos, eye);\n\tgl_FragColor = color;\n\n}","lights":false},"onBeforeCompileDataJSON":{"vertexShader":"precision highp float;\nprecision highp int;\n\nvarying vec3 vPw;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n\n\n\n\nvoid main()\t{\n\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\n\n\n\n\tvPw = position;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}","fragmentShader":"precision highp float;\nprecision highp int;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 q = abs(p) - b;\n\treturn length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);\n}\n\n\nfloat opUnion( float d1, float d2 ) { return min(d1,d2); }\nfloat opSubtraction( float d1, float d2 ) { return max(-d1,d2); }\nfloat opIntersection( float d1, float d2 ) { return max(d1,d2); }\n\nfloat opSmoothUnion( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) - k*h*(1.0-h);\n}\n\nfloat opSmoothSubtraction( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );\n\treturn mix( d2, -d1, h ) + k*h*(1.0-h);\n}\n\nfloat opSmoothIntersection( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) + k*h*(1.0-h);\n}\n\n// /metaball_volume/MAT/volumeBuilder1/rotate1\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// /metaball_volume/MAT/volumeBuilder1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n// /metaball_volume/MAT/volumeBuilder1/param1\nuniform vec3 v_POLY_param_cursor;\n\n\n\n\n\n#define DIR_LIGHTS_COUNT 1\n#define MAX_STEPS_COUNT 4096\n\nuniform vec3 u_Color;\nuniform float u_VolumeDensity;\nuniform float u_ShadowDensity;\nuniform float u_StepSize;\nuniform vec3 u_BoundingBoxMin;\nuniform vec3 u_BoundingBoxMax;\n//const int u_PointsCount = 3;\n//uniform vec3 u_Points[3];\nuniform sampler2D u_Map;\n\n//const int u_DirectionalLightsCount = 1;\nuniform vec3 u_DirectionalLightDirection; //[DIR_LIGHTS_COUNT];\n\nvarying vec3 vPw;\n// varying vec3 vN;\n// varying vec2 vUV;\n//varying vec3 vPCameraSpace;\n// varying vec4 vCd;\n\nvec3 normalize_in_bbox(vec3 point){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn vec3(\n\t\t(point.x - min.x) / (max.x - min.x),\n\t\t(point.y - min.y) / (max.y - min.y),\n\t\t(point.z - min.z) / (max.z - min.z)\n\t);\n}\n\nbool is_inside_bbox(vec3 Pw){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn (\n\t\tPw.x > min.x &&\n\t\tPw.y > min.y &&\n\t\tPw.z > min.z &&\n\n\t\tPw.x < max.x &&\n\t\tPw.y < max.y &&\n\t\tPw.z < max.z\n\t\t);\n}\n\nfloat density_to_opacity(float density, float step_size){\n\tfloat curent_density = density;\n\tcurent_density = max(0.0, curent_density);\n\n\tfloat opacity = (1.0-exp(-curent_density * step_size));\n\treturn max(opacity,0.0);\n}\n\nfloat density_function(vec3 position_for_step){\n\tfloat density = 1.0;\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/constant1\n\tfloat v_POLY_constant1_val = 0.02;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals1\n\tvec3 v_POLY_globals1_position = position_for_step;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/add1\n\tfloat v_POLY_add1_sum = (v_POLY_constant1_val + 0.01);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n\tfloat v_POLY_SDFSphere2_float = sdSphere(v_POLY_globals1_position - v_POLY_param1_val, 0.43);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate1\n\tvec3 v_POLY_rotate1_val = rotateWithAxisAngle(v_POLY_constant2_val, vec3(0.0, 1.0, 0.0), v_POLY_globals2_time);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/multAdd1\n\tfloat v_POLY_multAdd1_val = (1.33*(v_POLY_globals3_time + 6.0)) + 0.0;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere1\n\tfloat v_POLY_SDFSphere1_float = sdSphere(v_POLY_globals1_position - v_POLY_rotate1_val, 0.4);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate2\n\tvec3 v_POLY_rotate2_val = rotateWithAxisAngle(v_POLY_constant3_val, vec3(1.0, 0.0, 0.0), v_POLY_multAdd1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFBox1\n\tfloat v_POLY_SDFBox1_float = sdBox(v_POLY_globals1_position - v_POLY_rotate2_val, vec3(0.32000000000000006, 0.32000000000000006, 0.32000000000000006));\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion2\n\tfloat v_POLY_SDFUnion2_union = opSmoothUnion(v_POLY_SDFSphere1_float, v_POLY_SDFBox1_float, 0.23);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion1\n\tfloat v_POLY_SDFUnion1_union = opSmoothUnion(v_POLY_SDFUnion2_union, v_POLY_SDFSphere2_float, 0.31);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(v_POLY_constant1_val, v_POLY_add1_sum, v_POLY_SDFUnion1_union);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_smoothstep1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/output1\n\tdensity *= v_POLY_complement1_val;\n\n\n\n\n\treturn density;\n}\n\nvec4 raymarch_light(vec3 ray_dir, vec3 start_pos){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos + step_vector*rand(start_pos.x*ray_dir.xy);\n\tfloat opacity = 0.0;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( is_inside_bbox(current_pos) ){\n\n\t\t\tfloat density = density_function(current_pos) * u_ShadowDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\t\t\tcurrent_pos += step_vector;\n\n\t\t}else{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvec3 light_color = vec3(1.0, 1.0, 1.0) * u_Color;\n\tlight_color *= (1.0-opacity);\n\treturn vec4(light_color, 1.0-opacity);\n}\n\nvec4 raymarch_bbox(vec3 start_pos, vec3 ray_dir){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos - step_vector*rand(ray_dir.xz);\n\tfloat opacity = 0.0;\n\tvec3 color = vec3(0.0, 0.0, 0.0);\n\tfloat steps_count = 0.0;\n\tbool was_inside_bbox = false;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( i==0 || is_inside_bbox(current_pos) ){\n\t\t\twas_inside_bbox = true;\n\n\t\t\tfloat density = density_function(current_pos) * u_VolumeDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\n\t\t\tvec4 light_color = vec4(0.0,0.0,0.0,1.0); //vec4(1.0,1.0,1.0,1.0);\n\t\t\t// vec3 directional_light_direction;\n\t\t\t// for ( int l = 0; l < DIR_LIGHTS_COUNT; l++ ) {\n\t\t\t// directional_light_direction = u_DirectionalLightsDirection[ l ];\n\t\t\tlight_color += raymarch_light(-u_DirectionalLightDirection, current_pos);\n\t\t\t// }\n\t\t\tfloat blend = 1.0-opacity;\n\t\t\tcolor = mix( color.xyz, light_color.xyz, vec3(blend, blend, blend) );\n\t\t\tsteps_count += 1.0;\n\n\t\t}else{\n\t\t\tif (was_inside_bbox) { break; }\n\t\t}\n\t\tcurrent_pos += step_vector;\n\t}\n\n\treturn vec4(color, opacity);\n\t// steps_count = steps_count / 5.0;\n\t// return vec4(vec3(steps_count, steps_count, steps_count), 1.0);\n}\n\nvoid main()\t{\n\n\tvec3 eye = normalize(vPw - cameraPosition);\n\t// we can start from the bbox, as we are front facing\n\tvec3 start_pos = vPw;\n\n\tvec4 color = raymarch_bbox(start_pos, eye);\n\tgl_FragColor = color;\n\n}","timeDependent":true,"resolutionDependent":false,"paramConfigs":[{"type":"vector3","name":"cursor","defaultValue":[0,0,0],"uniformName":"v_POLY_param_cursor"}]},"customMaterials":{}}}},"selection":["volumeBuilder1"]},"eventsNetwork1":{"type":"eventsNetwork","nodes":{"raycast1":{"type":"raycast","params":{"mouse":[0.8395833333333333,0.3923233695652174],"intersectWith":1,"planeDirection":[0,0,1],"tpositionTarget":1,"position":[-1.6683963350967843,-1.92866583507242,0],"positionTarget":"../../MAT/volumeBuilder1/cursor"},"inputs":[{"index":0,"node":"pointer1","output":"pointermove"}]},"pointer1":{"type":"pointer","params":{"pointerdown":0,"pointermove":1}}}}},"flags":{"display":true}}},"params":{"mainCameraPath":"/perspectiveCamera1"},"selection":["metaball_volume"]},"ui":{"nodes":{"hemisphereLight1":{"pos":[150,100]},"perspectiveCamera1":{"pos":[-200,100],"nodes":{"events1":{"pos":[-200,50],"nodes":{"cameraOrbitControls1":{"pos":[150,50]}}}}},"COP":{"pos":[-200,200],"nodes":{"imageEnv":{"pos":[50,100]},"imageUv":{"pos":[-100,100]},"envMap":{"pos":[50,200]}}},"background_wall":{"pos":[-50,-250],"nodes":{"MAT":{"pos":[-200,-50],"nodes":{"meshStandard1":{"pos":[0,0]}}},"material1":{"pos":[0,-50]},"plane1":{"pos":[0,-150]}}},"lights":{"pos":[-50,-50],"nodes":{"areaLight1":{"pos":[-100,-100]},"hemisphereLight1":{"pos":[100,-100]},"merge1":{"pos":[-100,250]},"polarTransform1":{"pos":[-300,50]},"polarTransform2":{"pos":[-100,50]},"spotLight1":{"pos":[-300,-100]}}},"metaball_volume":{"pos":[-50,-150],"nodes":{"box1":{"pos":[50,200]},"material1":{"pos":[50,400]},"MAT":{"pos":[-200,300],"nodes":{"volumeBuilder1":{"pos":[-50,-100],"nodes":{"globals1":{"pos":[-600,50]},"output1":{"pos":[450,-150]},"SDFSphere1":{"pos":[-300,-300]},"smoothstep1":{"pos":[250,-150]},"complement1":{"pos":[350,-150]},"SDFSphere2":{"pos":[-200,150]},"SDFUnion1":{"pos":[-50,50]},"constant1":{"pos":[-50,-300]},"add1":{"pos":[50,-100]},"constant2":{"pos":[-650,-500]},"rotate1":{"pos":[-450,-450]},"globals2":{"pos":[-650,-400]},"param1":{"pos":[-550,250]},"SDFBox1":{"pos":[-300,-150]},"constant3":{"pos":[-750,-200]},"rotate2":{"pos":[-550,-150]},"globals3":{"pos":[-750,-100]},"multAdd1":{"pos":[-650,-100]},"SDFUnion2":{"pos":[-200,-250]}}}}},"eventsNetwork1":{"pos":[-200,450],"nodes":{"raycast1":{"pos":[-50,-50]},"pointer1":{"pos":[-250,-50]}}}}}}}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/perspectiveCamera1","linkIndex":1}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":108.54445975522286,"y":-309.6268989731344},"zoom":0.8310048773052896},"history":{"2":{"position":{"x":-48,"y":-22},"zoom":0.5},"3":{"position":{"x":-48,"y":-22},"zoom":0.5},"6":{"position":{"x":11.339999999999996,"y":-96.49999999999999},"zoom":0.6172839506172841},"9":{"position":{"x":-32,"y":-88},"zoom":0.5},"33":{"position":{"x":-43,"y":-332},"zoom":0.617283950617284},"131":{"position":{"x":-59.04899999999998,"y":-65.1854},"zoom":0.8467543904215146},"150":{"position":{"x":108.54445975522286,"y":-309.6268989731344},"zoom":0.8310048773052896},"377":{"position":{"x":200,"y":50},"zoom":0.5},"516":{"position":{"x":100,"y":-75},"zoom":0.5},"530":{"position":{"x":50,"y":100},"zoom":0.8310048773052896},"561":{"position":{"x":289.17489743805703,"y":135.49567082022574},"zoom":0.8310048773052896},"654":{"position":{"x":-42.12,"y":11.34},"zoom":0.617283950617284},"732":{"position":{"x":289.17489743805703,"y":135.49567082022574},"zoom":0.8310048773052896},"1032":{"position":{"x":0,"y":0},"zoom":1.0453757906438452}},"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/metaball_volume","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/","/metaball_volume","/","/lights","/","/metaball_volume","/","/background_wall","/","/metaball_volume","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/eventsNetwork1","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/","/background_wall","/","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":37,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"createExport":true,"compressJs":true,"publishToIntegrations":false},"paramsModal":[]}
Used nodes
cop/envMap;cop/image;cop/imageEXR;event/cameraOrbitControls;event/pointer;event/raycast;mat/meshStandard;mat/volumeBuilder;obj/copNetwork;obj/geo;obj/hemisphereLight;obj/perspectiveCamera;sop/areaLight;sop/box;sop/eventsNetwork;sop/hemisphereLight;sop/material;sop/materialsNetwork;sop/merge;sop/plane;sop/polarTransform;sop/spotLight
Used operations
Used modules
Used assemblers
GL_VOLUME
Used integrations
[]
Used assets
Nodes map
{"/hemisphereLight1":"obj/hemisphereLight","/perspectiveCamera1":"obj/perspectiveCamera","/perspectiveCamera1/events1":"sop/eventsNetwork","/perspectiveCamera1/events1/cameraOrbitControls1":"event/cameraOrbitControls","/COP":"obj/copNetwork","/COP/imageEnv":"cop/imageEXR","/COP/imageUv":"cop/image","/COP/envMap":"cop/envMap","/background_wall":"obj/geo","/background_wall/MAT":"sop/materialsNetwork","/background_wall/MAT/meshStandard1":"mat/meshStandard","/background_wall/material1":"sop/material","/background_wall/plane1":"sop/plane","/lights":"obj/geo","/lights/areaLight1":"sop/areaLight","/lights/hemisphereLight1":"sop/hemisphereLight","/lights/merge1":"sop/merge","/lights/polarTransform1":"sop/polarTransform","/lights/polarTransform2":"sop/polarTransform","/lights/spotLight1":"sop/spotLight","/metaball_volume":"obj/geo","/metaball_volume/box1":"sop/box","/metaball_volume/material1":"sop/material","/metaball_volume/MAT":"sop/materialsNetwork","/metaball_volume/MAT/volumeBuilder1":"mat/volumeBuilder","/metaball_volume/eventsNetwork1":"sop/eventsNetwork","/metaball_volume/eventsNetwork1/raycast1":"event/raycast","/metaball_volume/eventsNetwork1/pointer1":"event/pointer"}
Js version
Editor version
Engine version
Name
*
Code
{"properties":{"frame":1769,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/perspectiveCamera1","versions":{"polygonjs":"1.1.262"}},"root":{"type":"root","nodes":{"hemisphereLight1":{"type":"hemisphereLight","flags":{"display":true}},"perspectiveCamera1":{"type":"perspectiveCamera","nodes":{"events1":{"type":"eventsNetwork","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[-0.32778130444084347,-0.192630758771347,-0.07727433770887207]}}},"selection":["cameraOrbitControls1"]}},"params":{"t":[3.0161526633531355,1.1787657307191874,2.814738208647524],"r":[-22.723127930556515,44.66532130223666,16.403892417511617],"controls":"./events1/cameraOrbitControls1"},"flags":{"display":true}},"COP":{"type":"copNetwork","nodes":{"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}},"envMap":{"type":"envMap","inputs":["imageEnv"]}}},"background_wall":{"type":"geo","nodes":{"MAT":{"type":"materialsNetwork","nodes":{"meshStandard1":{"type":"meshStandard","params":{"metalness":0,"roughness":1}}}},"material1":{"type":"material","params":{"material":"../MAT/meshStandard1"},"inputs":["plane1"],"flags":{"display":true}},"plane1":{"type":"plane","params":{"size":[23,23],"direction":[0,0,1],"center":[0,0,-2.6]}}},"flags":{"display":true}},"lights":{"type":"geo","nodes":{"areaLight1":{"type":"areaLight","params":{"width":1.6,"showHelper":true}},"hemisphereLight1":{"type":"hemisphereLight"},"merge1":{"type":"merge","inputs":["polarTransform1","polarTransform2","hemisphereLight1"],"flags":{"display":true}},"polarTransform1":{"type":"polarTransform","params":{"longitude":64.8,"latitude":36,"depth":2.8},"inputs":["spotLight1"]},"polarTransform2":{"type":"polarTransform","params":{"longitude":295.2,"latitude":-72,"depth":2.5},"inputs":["areaLight1"]},"spotLight1":{"type":"spotLight","params":{"penumbra":0.76}}},"flags":{"display":true}},"metaball_volume":{"type":"geo","nodes":{"box1":{"type":"box","params":{"size":2,"sizes":[1.7,1.5,1.7]}},"material1":{"type":"material","params":{"material":"../MAT/volumeBuilder1"},"inputs":["box1"],"flags":{"display":true}},"MAT":{"type":"materialsNetwork","nodes":{"volumeBuilder1":{"type":"volumeBuilder","nodes":{"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[{"index":0,"node":"complement1","output":"val"}]},"SDFSphere1":{"type":"SDFSphere","params":{"position":{"overriden_options":{}},"center":{"overriden_options":{}},"radius":{"raw_input":0.4,"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"rotate1","output":"val"}]},"smoothstep1":{"type":"smoothstep","params":{"edge0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false},"raw_input":0.22},"edge1":{"type":"float","default_value":1,"options":{"spare":true,"editable":false},"raw_input":0.25},"x":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"node":"constant1","output":"val"},{"index":1,"node":"add1","output":"sum"},{"index":2,"node":"SDFUnion1","output":"union"}],"connection_points":{"in":[{"name":"edge0","type":"float"},{"name":"edge1","type":"float"},{"name":"x","type":"float"}],"out":[{"name":"val","type":"float"}]}},"complement1":{"type":"complement","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"inputs":[{"index":0,"node":"smoothstep1","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"SDFSphere2":{"type":"SDFSphere","params":{"position":{"overriden_options":{}},"center":{"raw_input":[0.7,-0.8,0],"overriden_options":{}},"radius":{"raw_input":0.43,"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"param1","output":"val"}]},"SDFUnion1":{"type":"SDFUnion","params":{"sdf0":{"overriden_options":{}},"sdf1":{"overriden_options":{}},"smooth":{"raw_input":1,"overriden_options":{}},"smoothFactor":{"raw_input":0.31,"overriden_options":{}}},"inputs":[{"index":0,"node":"SDFUnion2","output":"union"},{"index":1,"node":"SDFSphere2","output":"float"}]},"constant1":{"type":"constant","params":{"float":0.02},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"add1":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":true},"raw_input":0.01}},"inputs":[{"index":0,"node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float"},{"name":"add1","type":"float"}],"out":[{"name":"sum","type":"float"}]}},"constant2":{"type":"constant","params":{"type":4,"vec3":[0,0,0.6]},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"rotate1":{"type":"rotate","params":{"vector":{"type":"vector3","default_value":[0,0,1],"options":{"spare":true,"editable":false}},"axis":{"type":"vector3","default_value":[0,1,0],"options":{"spare":true,"editable":true}},"angle":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":3,"inputs":[{"index":0,"node":"constant2","output":"val"},null,{"index":2,"node":"globals2","output":"time"}],"connection_points":{"in":[{"name":"vector","type":"vec3"},{"name":"axis","type":"vec3"},{"name":"angle","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"globals2":{"type":"globals"},"param1":{"type":"param","params":{"name":"cursor","type":4},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"SDFBox1":{"type":"SDFBox","params":{"position":{"overriden_options":{}},"center":{"overriden_options":{}},"size":{"raw_input":[0.32000000000000006,0.32000000000000006,0.32000000000000006],"overriden_options":{}}},"inputs":[{"index":0,"node":"globals1","output":"position"},{"index":1,"node":"rotate2","output":"val"}]},"constant3":{"type":"constant","params":{"type":4,"vec3":[0,0,0.6]},"connection_points":{"in":[],"out":[{"name":"val","type":"vec3"}]}},"rotate2":{"type":"rotate","params":{"vector":{"type":"vector3","default_value":[0,0,1],"options":{"spare":true,"editable":false}},"axis":{"type":"vector3","default_value":[0,1,0],"options":{"spare":true,"editable":true},"raw_input":[1,0,0]},"angle":{"type":"float","default_value":0,"options":{"spare":true,"editable":false}}},"maxInputsCount":3,"inputs":[{"index":0,"node":"constant3","output":"val"},null,{"index":2,"node":"multAdd1","output":"val"}],"connection_points":{"in":[{"name":"vector","type":"vec3"},{"name":"axis","type":"vec3"},{"name":"angle","type":"float"}],"out":[{"name":"val","type":"vec3"}]}},"globals3":{"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},"raw_input":6},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true},"raw_input":1.33},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true}}},"inputs":[{"index":0,"node":"globals3","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"}]}},"SDFUnion2":{"type":"SDFUnion","params":{"sdf0":{"overriden_options":{}},"sdf1":{"overriden_options":{}},"smooth":{"raw_input":1,"overriden_options":{}},"smoothFactor":{"raw_input":0.23,"overriden_options":{}}},"inputs":[{"index":0,"node":"SDFSphere1","output":"float"},{"index":1,"node":"SDFBox1","output":"float"}]}},"params":{"color":[0.43529411764705883,0.5019607843137255,0.7647058823529411],"stepSize":0.12,"density":3.96,"shadowDensity":0.74,"lightDir":[0.7,0.8,-1],"cursor":{"type":"vector3","default_value":[0,0,0],"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":[5.5954644323425295,0.8462119493215142,0],"overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.5,"type":"Material","generator":"Material.toJSON"},"uuid":"/metaball_volume/MAT/volumeBuilder1-main","type":"ShaderMaterial","name":"/metaball_volume/MAT/volumeBuilder1","color":16777215,"transparent":true,"depthFunc":3,"depthTest":true,"depthWrite":true,"colorWrite":true,"stencilWrite":false,"stencilWriteMask":255,"stencilFunc":519,"stencilRef":0,"stencilFuncMask":255,"stencilFail":7680,"stencilZFail":7680,"stencilZPass":7680,"glslVersion":null,"uniforms":{"u_Color":{"type":"c","value":7307459},"u_VolumeDensity":{"value":3.96},"u_ShadowDensity":{"value":0.74},"u_StepSize":{"value":0.12},"u_BoundingBoxMin":{"type":"v3","value":[-1.7000000476837158,-1.5,-1.7000000476837158]},"u_BoundingBoxMax":{"type":"v3","value":[1.7000000476837158,1.5,1.7000000476837158]},"u_DirectionalLightDirection":{"type":"v3","value":[0.7,0.8,-1]},"v_POLY_param_cursor":{"type":"v3","value":[5.5954644323425295,0.8462119493215142,0]},"time":{"value":29.483333333333334}},"vertexShader":"precision highp float;\nprecision highp int;\n\nvarying vec3 vPw;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n\n\n\n\nvoid main()\t{\n\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\n\n\n\n\tvPw = position;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}","fragmentShader":"precision highp float;\nprecision highp int;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 q = abs(p) - b;\n\treturn length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);\n}\n\n\nfloat opUnion( float d1, float d2 ) { return min(d1,d2); }\nfloat opSubtraction( float d1, float d2 ) { return max(-d1,d2); }\nfloat opIntersection( float d1, float d2 ) { return max(d1,d2); }\n\nfloat opSmoothUnion( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) - k*h*(1.0-h);\n}\n\nfloat opSmoothSubtraction( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );\n\treturn mix( d2, -d1, h ) + k*h*(1.0-h);\n}\n\nfloat opSmoothIntersection( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) + k*h*(1.0-h);\n}\n\n// /metaball_volume/MAT/volumeBuilder1/rotate1\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// /metaball_volume/MAT/volumeBuilder1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n// /metaball_volume/MAT/volumeBuilder1/param1\nuniform vec3 v_POLY_param_cursor;\n\n\n\n\n\n#define DIR_LIGHTS_COUNT 1\n#define MAX_STEPS_COUNT 4096\n\nuniform vec3 u_Color;\nuniform float u_VolumeDensity;\nuniform float u_ShadowDensity;\nuniform float u_StepSize;\nuniform vec3 u_BoundingBoxMin;\nuniform vec3 u_BoundingBoxMax;\n//const int u_PointsCount = 3;\n//uniform vec3 u_Points[3];\nuniform sampler2D u_Map;\n\n//const int u_DirectionalLightsCount = 1;\nuniform vec3 u_DirectionalLightDirection; //[DIR_LIGHTS_COUNT];\n\nvarying vec3 vPw;\n// varying vec3 vN;\n// varying vec2 vUV;\n//varying vec3 vPCameraSpace;\n// varying vec4 vCd;\n\nvec3 normalize_in_bbox(vec3 point){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn vec3(\n\t\t(point.x - min.x) / (max.x - min.x),\n\t\t(point.y - min.y) / (max.y - min.y),\n\t\t(point.z - min.z) / (max.z - min.z)\n\t);\n}\n\nbool is_inside_bbox(vec3 Pw){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn (\n\t\tPw.x > min.x &&\n\t\tPw.y > min.y &&\n\t\tPw.z > min.z &&\n\n\t\tPw.x < max.x &&\n\t\tPw.y < max.y &&\n\t\tPw.z < max.z\n\t\t);\n}\n\nfloat density_to_opacity(float density, float step_size){\n\tfloat curent_density = density;\n\tcurent_density = max(0.0, curent_density);\n\n\tfloat opacity = (1.0-exp(-curent_density * step_size));\n\treturn max(opacity,0.0);\n}\n\nfloat density_function(vec3 position_for_step){\n\tfloat density = 1.0;\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/constant1\n\tfloat v_POLY_constant1_val = 0.02;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals1\n\tvec3 v_POLY_globals1_position = position_for_step;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/add1\n\tfloat v_POLY_add1_sum = (v_POLY_constant1_val + 0.01);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n\tfloat v_POLY_SDFSphere2_float = sdSphere(v_POLY_globals1_position - v_POLY_param1_val, 0.43);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate1\n\tvec3 v_POLY_rotate1_val = rotateWithAxisAngle(v_POLY_constant2_val, vec3(0.0, 1.0, 0.0), v_POLY_globals2_time);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/multAdd1\n\tfloat v_POLY_multAdd1_val = (1.33*(v_POLY_globals3_time + 6.0)) + 0.0;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere1\n\tfloat v_POLY_SDFSphere1_float = sdSphere(v_POLY_globals1_position - v_POLY_rotate1_val, 0.4);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate2\n\tvec3 v_POLY_rotate2_val = rotateWithAxisAngle(v_POLY_constant3_val, vec3(1.0, 0.0, 0.0), v_POLY_multAdd1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFBox1\n\tfloat v_POLY_SDFBox1_float = sdBox(v_POLY_globals1_position - v_POLY_rotate2_val, vec3(0.32000000000000006, 0.32000000000000006, 0.32000000000000006));\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion2\n\tfloat v_POLY_SDFUnion2_union = opSmoothUnion(v_POLY_SDFSphere1_float, v_POLY_SDFBox1_float, 0.23);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion1\n\tfloat v_POLY_SDFUnion1_union = opSmoothUnion(v_POLY_SDFUnion2_union, v_POLY_SDFSphere2_float, 0.31);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(v_POLY_constant1_val, v_POLY_add1_sum, v_POLY_SDFUnion1_union);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_smoothstep1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/output1\n\tdensity *= v_POLY_complement1_val;\n\n\n\n\n\treturn density;\n}\n\nvec4 raymarch_light(vec3 ray_dir, vec3 start_pos){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos + step_vector*rand(start_pos.x*ray_dir.xy);\n\tfloat opacity = 0.0;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( is_inside_bbox(current_pos) ){\n\n\t\t\tfloat density = density_function(current_pos) * u_ShadowDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\t\t\tcurrent_pos += step_vector;\n\n\t\t}else{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvec3 light_color = vec3(1.0, 1.0, 1.0) * u_Color;\n\tlight_color *= (1.0-opacity);\n\treturn vec4(light_color, 1.0-opacity);\n}\n\nvec4 raymarch_bbox(vec3 start_pos, vec3 ray_dir){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos - step_vector*rand(ray_dir.xz);\n\tfloat opacity = 0.0;\n\tvec3 color = vec3(0.0, 0.0, 0.0);\n\tfloat steps_count = 0.0;\n\tbool was_inside_bbox = false;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( i==0 || is_inside_bbox(current_pos) ){\n\t\t\twas_inside_bbox = true;\n\n\t\t\tfloat density = density_function(current_pos) * u_VolumeDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\n\t\t\tvec4 light_color = vec4(0.0,0.0,0.0,1.0); //vec4(1.0,1.0,1.0,1.0);\n\t\t\t// vec3 directional_light_direction;\n\t\t\t// for ( int l = 0; l < DIR_LIGHTS_COUNT; l++ ) {\n\t\t\t// directional_light_direction = u_DirectionalLightsDirection[ l ];\n\t\t\tlight_color += raymarch_light(-u_DirectionalLightDirection, current_pos);\n\t\t\t// }\n\t\t\tfloat blend = 1.0-opacity;\n\t\t\tcolor = mix( color.xyz, light_color.xyz, vec3(blend, blend, blend) );\n\t\t\tsteps_count += 1.0;\n\n\t\t}else{\n\t\t\tif (was_inside_bbox) { break; }\n\t\t}\n\t\tcurrent_pos += step_vector;\n\t}\n\n\treturn vec4(color, opacity);\n\t// steps_count = steps_count / 5.0;\n\t// return vec4(vec3(steps_count, steps_count, steps_count), 1.0);\n}\n\nvoid main()\t{\n\n\tvec3 eye = normalize(vPw - cameraPosition);\n\t// we can start from the bbox, as we are front facing\n\tvec3 start_pos = vPw;\n\n\tvec4 color = raymarch_bbox(start_pos, eye);\n\tgl_FragColor = color;\n\n}","lights":false},"onBeforeCompileDataJSON":{"vertexShader":"precision highp float;\nprecision highp int;\n\nvarying vec3 vPw;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n\n\n\n\nvoid main()\t{\n\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\n\n\n\n\tvPw = position;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}","fragmentShader":"precision highp float;\nprecision highp int;\n\n#include <common>\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n// https://iquilezles.org/www/articles/distfunctions/distfunctions.htm\n\nfloat sdSphere( vec3 p, float s )\n{\n\treturn length(p)-s;\n}\n\nfloat sdBox( vec3 p, vec3 b )\n{\n\tvec3 q = abs(p) - b;\n\treturn length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);\n}\n\n\nfloat opUnion( float d1, float d2 ) { return min(d1,d2); }\nfloat opSubtraction( float d1, float d2 ) { return max(-d1,d2); }\nfloat opIntersection( float d1, float d2 ) { return max(d1,d2); }\n\nfloat opSmoothUnion( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) - k*h*(1.0-h);\n}\n\nfloat opSmoothSubtraction( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );\n\treturn mix( d2, -d1, h ) + k*h*(1.0-h);\n}\n\nfloat opSmoothIntersection( float d1, float d2, float k ) {\n\tfloat h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );\n\treturn mix( d2, d1, h ) + k*h*(1.0-h);\n}\n\n// /metaball_volume/MAT/volumeBuilder1/rotate1\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// /metaball_volume/MAT/volumeBuilder1/complement1\nfloat complement(float x){return 1.0-x;}\nvec2 complement(vec2 x){return vec2(1.0-x.x, 1.0-x.y);}\nvec3 complement(vec3 x){return vec3(1.0-x.x, 1.0-x.y, 1.0-x.z);}\nvec4 complement(vec4 x){return vec4(1.0-x.x, 1.0-x.y, 1.0-x.z, 1.0-x.w);}\n\n\n\n\n\n\n\n\n// /metaball_volume/MAT/volumeBuilder1/globals2\nuniform float time;\n\n// /metaball_volume/MAT/volumeBuilder1/param1\nuniform vec3 v_POLY_param_cursor;\n\n\n\n\n\n#define DIR_LIGHTS_COUNT 1\n#define MAX_STEPS_COUNT 4096\n\nuniform vec3 u_Color;\nuniform float u_VolumeDensity;\nuniform float u_ShadowDensity;\nuniform float u_StepSize;\nuniform vec3 u_BoundingBoxMin;\nuniform vec3 u_BoundingBoxMax;\n//const int u_PointsCount = 3;\n//uniform vec3 u_Points[3];\nuniform sampler2D u_Map;\n\n//const int u_DirectionalLightsCount = 1;\nuniform vec3 u_DirectionalLightDirection; //[DIR_LIGHTS_COUNT];\n\nvarying vec3 vPw;\n// varying vec3 vN;\n// varying vec2 vUV;\n//varying vec3 vPCameraSpace;\n// varying vec4 vCd;\n\nvec3 normalize_in_bbox(vec3 point){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn vec3(\n\t\t(point.x - min.x) / (max.x - min.x),\n\t\t(point.y - min.y) / (max.y - min.y),\n\t\t(point.z - min.z) / (max.z - min.z)\n\t);\n}\n\nbool is_inside_bbox(vec3 Pw){\n\n\tvec3 min = u_BoundingBoxMin;\n\tvec3 max = u_BoundingBoxMax;\n\n\treturn (\n\t\tPw.x > min.x &&\n\t\tPw.y > min.y &&\n\t\tPw.z > min.z &&\n\n\t\tPw.x < max.x &&\n\t\tPw.y < max.y &&\n\t\tPw.z < max.z\n\t\t);\n}\n\nfloat density_to_opacity(float density, float step_size){\n\tfloat curent_density = density;\n\tcurent_density = max(0.0, curent_density);\n\n\tfloat opacity = (1.0-exp(-curent_density * step_size));\n\treturn max(opacity,0.0);\n}\n\nfloat density_function(vec3 position_for_step){\n\tfloat density = 1.0;\n\t// start builder body code\n\n\n\n\t// /metaball_volume/MAT/volumeBuilder1/constant1\n\tfloat v_POLY_constant1_val = 0.02;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals1\n\tvec3 v_POLY_globals1_position = position_for_step;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant2\n\tvec3 v_POLY_constant2_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals2\n\tfloat v_POLY_globals2_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/constant3\n\tvec3 v_POLY_constant3_val = vec3(0.0, 0.0, 0.6);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/globals3\n\tfloat v_POLY_globals3_time = time;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/param1\n\tvec3 v_POLY_param1_val = v_POLY_param_cursor;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/add1\n\tfloat v_POLY_add1_sum = (v_POLY_constant1_val + 0.01);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere2\n\tfloat v_POLY_SDFSphere2_float = sdSphere(v_POLY_globals1_position - v_POLY_param1_val, 0.43);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate1\n\tvec3 v_POLY_rotate1_val = rotateWithAxisAngle(v_POLY_constant2_val, vec3(0.0, 1.0, 0.0), v_POLY_globals2_time);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/multAdd1\n\tfloat v_POLY_multAdd1_val = (1.33*(v_POLY_globals3_time + 6.0)) + 0.0;\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFSphere1\n\tfloat v_POLY_SDFSphere1_float = sdSphere(v_POLY_globals1_position - v_POLY_rotate1_val, 0.4);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/rotate2\n\tvec3 v_POLY_rotate2_val = rotateWithAxisAngle(v_POLY_constant3_val, vec3(1.0, 0.0, 0.0), v_POLY_multAdd1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFBox1\n\tfloat v_POLY_SDFBox1_float = sdBox(v_POLY_globals1_position - v_POLY_rotate2_val, vec3(0.32000000000000006, 0.32000000000000006, 0.32000000000000006));\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion2\n\tfloat v_POLY_SDFUnion2_union = opSmoothUnion(v_POLY_SDFSphere1_float, v_POLY_SDFBox1_float, 0.23);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/SDFUnion1\n\tfloat v_POLY_SDFUnion1_union = opSmoothUnion(v_POLY_SDFUnion2_union, v_POLY_SDFSphere2_float, 0.31);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/smoothstep1\n\tfloat v_POLY_smoothstep1_val = smoothstep(v_POLY_constant1_val, v_POLY_add1_sum, v_POLY_SDFUnion1_union);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/complement1\n\tfloat v_POLY_complement1_val = complement(v_POLY_smoothstep1_val);\n\t\n\t// /metaball_volume/MAT/volumeBuilder1/output1\n\tdensity *= v_POLY_complement1_val;\n\n\n\n\n\treturn density;\n}\n\nvec4 raymarch_light(vec3 ray_dir, vec3 start_pos){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos + step_vector*rand(start_pos.x*ray_dir.xy);\n\tfloat opacity = 0.0;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( is_inside_bbox(current_pos) ){\n\n\t\t\tfloat density = density_function(current_pos) * u_ShadowDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\t\t\tcurrent_pos += step_vector;\n\n\t\t}else{\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tvec3 light_color = vec3(1.0, 1.0, 1.0) * u_Color;\n\tlight_color *= (1.0-opacity);\n\treturn vec4(light_color, 1.0-opacity);\n}\n\nvec4 raymarch_bbox(vec3 start_pos, vec3 ray_dir){\n\n\tfloat step_size = u_StepSize;\n\tvec3 step_vector = ray_dir * step_size;\n\n\tvec3 current_pos = start_pos - step_vector*rand(ray_dir.xz);\n\tfloat opacity = 0.0;\n\tvec3 color = vec3(0.0, 0.0, 0.0);\n\tfloat steps_count = 0.0;\n\tbool was_inside_bbox = false;\n\tfor(int i=0; i<MAX_STEPS_COUNT; i++){\n\t\tif(opacity >= 0.99){ break; }\n\n\t\tif( i==0 || is_inside_bbox(current_pos) ){\n\t\t\twas_inside_bbox = true;\n\n\t\t\tfloat density = density_function(current_pos) * u_VolumeDensity;\n\t\t\topacity += density_to_opacity(density, step_size);\n\n\t\t\tvec4 light_color = vec4(0.0,0.0,0.0,1.0); //vec4(1.0,1.0,1.0,1.0);\n\t\t\t// vec3 directional_light_direction;\n\t\t\t// for ( int l = 0; l < DIR_LIGHTS_COUNT; l++ ) {\n\t\t\t// directional_light_direction = u_DirectionalLightsDirection[ l ];\n\t\t\tlight_color += raymarch_light(-u_DirectionalLightDirection, current_pos);\n\t\t\t// }\n\t\t\tfloat blend = 1.0-opacity;\n\t\t\tcolor = mix( color.xyz, light_color.xyz, vec3(blend, blend, blend) );\n\t\t\tsteps_count += 1.0;\n\n\t\t}else{\n\t\t\tif (was_inside_bbox) { break; }\n\t\t}\n\t\tcurrent_pos += step_vector;\n\t}\n\n\treturn vec4(color, opacity);\n\t// steps_count = steps_count / 5.0;\n\t// return vec4(vec3(steps_count, steps_count, steps_count), 1.0);\n}\n\nvoid main()\t{\n\n\tvec3 eye = normalize(vPw - cameraPosition);\n\t// we can start from the bbox, as we are front facing\n\tvec3 start_pos = vPw;\n\n\tvec4 color = raymarch_bbox(start_pos, eye);\n\tgl_FragColor = color;\n\n}","timeDependent":true,"resolutionDependent":false,"paramConfigs":[{"type":"vector3","name":"cursor","defaultValue":[0,0,0],"uniformName":"v_POLY_param_cursor"}]},"customMaterials":{}}}},"selection":["volumeBuilder1"]},"eventsNetwork1":{"type":"eventsNetwork","nodes":{"raycast1":{"type":"raycast","params":{"mouse":[0.8395833333333333,0.3923233695652174],"intersectWith":1,"planeDirection":[0,0,1],"tpositionTarget":1,"position":[-1.6683963350967843,-1.92866583507242,0],"positionTarget":"../../MAT/volumeBuilder1/cursor"},"inputs":[{"index":0,"node":"pointer1","output":"pointermove"}]},"pointer1":{"type":"pointer","params":{"pointerdown":0,"pointermove":1}}}}},"flags":{"display":true}}},"params":{"mainCameraPath":"/perspectiveCamera1"},"selection":["metaball_volume"]},"ui":{"nodes":{"hemisphereLight1":{"pos":[150,100]},"perspectiveCamera1":{"pos":[-200,100],"nodes":{"events1":{"pos":[-200,50],"nodes":{"cameraOrbitControls1":{"pos":[150,50]}}}}},"COP":{"pos":[-200,200],"nodes":{"imageEnv":{"pos":[50,100]},"imageUv":{"pos":[-100,100]},"envMap":{"pos":[50,200]}}},"background_wall":{"pos":[-50,-250],"nodes":{"MAT":{"pos":[-200,-50],"nodes":{"meshStandard1":{"pos":[0,0]}}},"material1":{"pos":[0,-50]},"plane1":{"pos":[0,-150]}}},"lights":{"pos":[-50,-50],"nodes":{"areaLight1":{"pos":[-100,-100]},"hemisphereLight1":{"pos":[100,-100]},"merge1":{"pos":[-100,250]},"polarTransform1":{"pos":[-300,50]},"polarTransform2":{"pos":[-100,50]},"spotLight1":{"pos":[-300,-100]}}},"metaball_volume":{"pos":[-50,-150],"nodes":{"box1":{"pos":[50,200]},"material1":{"pos":[50,400]},"MAT":{"pos":[-200,300],"nodes":{"volumeBuilder1":{"pos":[-50,-100],"nodes":{"globals1":{"pos":[-600,50]},"output1":{"pos":[450,-150]},"SDFSphere1":{"pos":[-300,-300]},"smoothstep1":{"pos":[250,-150]},"complement1":{"pos":[350,-150]},"SDFSphere2":{"pos":[-200,150]},"SDFUnion1":{"pos":[-50,50]},"constant1":{"pos":[-50,-300]},"add1":{"pos":[50,-100]},"constant2":{"pos":[-650,-500]},"rotate1":{"pos":[-450,-450]},"globals2":{"pos":[-650,-400]},"param1":{"pos":[-550,250]},"SDFBox1":{"pos":[-300,-150]},"constant3":{"pos":[-750,-200]},"rotate2":{"pos":[-550,-150]},"globals3":{"pos":[-750,-100]},"multAdd1":{"pos":[-650,-100]},"SDFUnion2":{"pos":[-200,-250]}}}}},"eventsNetwork1":{"pos":[-200,450],"nodes":{"raycast1":{"pos":[-50,-50]},"pointer1":{"pos":[-250,-50]}}}}}}}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/perspectiveCamera1","linkIndex":1}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":108.54445975522286,"y":-309.6268989731344},"zoom":0.8310048773052896},"history":{"2":{"position":{"x":-48,"y":-22},"zoom":0.5},"3":{"position":{"x":-48,"y":-22},"zoom":0.5},"6":{"position":{"x":11.339999999999996,"y":-96.49999999999999},"zoom":0.6172839506172841},"9":{"position":{"x":-32,"y":-88},"zoom":0.5},"33":{"position":{"x":-43,"y":-332},"zoom":0.617283950617284},"131":{"position":{"x":-59.04899999999998,"y":-65.1854},"zoom":0.8467543904215146},"150":{"position":{"x":108.54445975522286,"y":-309.6268989731344},"zoom":0.8310048773052896},"377":{"position":{"x":200,"y":50},"zoom":0.5},"516":{"position":{"x":100,"y":-75},"zoom":0.5},"530":{"position":{"x":50,"y":100},"zoom":0.8310048773052896},"561":{"position":{"x":289.17489743805703,"y":135.49567082022574},"zoom":0.8310048773052896},"654":{"position":{"x":-42.12,"y":11.34},"zoom":0.617283950617284},"732":{"position":{"x":289.17489743805703,"y":135.49567082022574},"zoom":0.8310048773052896},"1032":{"position":{"x":0,"y":0},"zoom":1.0453757906438452}},"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/metaball_volume","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/","/metaball_volume","/","/lights","/","/metaball_volume","/","/background_wall","/","/metaball_volume","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/metaball_volume/eventsNetwork1","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume","/","/background_wall","/","/metaball_volume","/metaball_volume/MAT","/metaball_volume/MAT/volumeBuilder1","/metaball_volume/MAT","/metaball_volume"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":37,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"createExport":true,"compressJs":true,"publishToIntegrations":false},"paramsModal":[]}
Used nodes
cop/envMap;cop/image;cop/imageEXR;event/cameraOrbitControls;event/pointer;event/raycast;mat/meshStandard;mat/volumeBuilder;obj/copNetwork;obj/geo;obj/hemisphereLight;obj/perspectiveCamera;sop/areaLight;sop/box;sop/eventsNetwork;sop/hemisphereLight;sop/material;sop/materialsNetwork;sop/merge;sop/plane;sop/polarTransform;sop/spotLight
Used operations
Used modules
Used assemblers
GL_VOLUME
Used integrations
[]
Used assets
Nodes map
{"/hemisphereLight1":"obj/hemisphereLight","/perspectiveCamera1":"obj/perspectiveCamera","/perspectiveCamera1/events1":"sop/eventsNetwork","/perspectiveCamera1/events1/cameraOrbitControls1":"event/cameraOrbitControls","/COP":"obj/copNetwork","/COP/imageEnv":"cop/imageEXR","/COP/imageUv":"cop/image","/COP/envMap":"cop/envMap","/background_wall":"obj/geo","/background_wall/MAT":"sop/materialsNetwork","/background_wall/MAT/meshStandard1":"mat/meshStandard","/background_wall/material1":"sop/material","/background_wall/plane1":"sop/plane","/lights":"obj/geo","/lights/areaLight1":"sop/areaLight","/lights/hemisphereLight1":"sop/hemisphereLight","/lights/merge1":"sop/merge","/lights/polarTransform1":"sop/polarTransform","/lights/polarTransform2":"sop/polarTransform","/lights/spotLight1":"sop/spotLight","/metaball_volume":"obj/geo","/metaball_volume/box1":"sop/box","/metaball_volume/material1":"sop/material","/metaball_volume/MAT":"sop/materialsNetwork","/metaball_volume/MAT/volumeBuilder1":"mat/volumeBuilder","/metaball_volume/eventsNetwork1":"sop/eventsNetwork","/metaball_volume/eventsNetwork1/raycast1":"event/raycast","/metaball_volume/eventsNetwork1/pointer1":"event/pointer"}
Js version
Editor version
Engine version
Logout
0%
There was a problem displaying your scene:
view scene source