├── geometry └── plane.json ├── index.html ├── js ├── Main.js ├── Utils.js └── elements │ ├── Gem.js │ ├── Sky.js │ └── Terrain.js ├── lib ├── three.min.js └── uil.min.js ├── readme.md └── shaders ├── Gem.fs ├── Gem.vs ├── Sky.fs ├── Sky.vs ├── Terrain.fs └── Terrain.vs /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FindingLove 10 | 11 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /js/Main.js: -------------------------------------------------------------------------------- 1 | class Main { 2 | constructor() { 3 | this.initThree(); 4 | this.resize(); 5 | this.initUIL(); 6 | requestAnimationFrame(this.render.bind(this)); 7 | } 8 | 9 | initThree () { 10 | this.scene = new THREE.Scene(); 11 | this.renderer = new THREE.WebGLRenderer(); 12 | this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); 13 | this.controls = new THREE.OrbitControls(this.camera); 14 | this.camera.position.z = 4; 15 | document.body.appendChild(this.renderer.domElement); 16 | window.onresize = () => this.resize(); 17 | 18 | let _this = this; 19 | 20 | let view = (function() { 21 | let hash = location.hash.slice(1); 22 | switch (hash) { 23 | case 'Gem': return new Gem(); break; 24 | case 'Sky': return new Sky(); break; 25 | case 'Terrain': 26 | _this.camera.position.z = 50; 27 | _this.camera.position.y = 30; 28 | return new Terrain(); 29 | break; 30 | default: throw 'No view found'; 31 | } 32 | })(); 33 | this.scene.add(view.group); 34 | this.view = view; 35 | } 36 | 37 | initUIL() { 38 | window.uil = new UIL.Gui({css:'top: 0; right: 50px;', size: 300, center: true}); 39 | } 40 | 41 | resize() { 42 | this.renderer.setSize(window.innerWidth, window.innerHeight); 43 | this.renderer.setPixelRatio(window.devicePixelRatio); 44 | } 45 | 46 | render() { 47 | this.view.update && this.view.update(); 48 | this.controls.update(); 49 | this.renderer.render(this.scene, this.camera); 50 | requestAnimationFrame(this.render.bind(this)); 51 | } 52 | } 53 | 54 | window.onload = () => new Main(); 55 | -------------------------------------------------------------------------------- /js/Utils.js: -------------------------------------------------------------------------------- 1 | class Utils { 2 | static toRadians(deg) { 3 | return deg * (Math.PI/180); 4 | } 5 | 6 | static headsTails(heads, tails) { 7 | return !Utils.doRandom(0, 1) ? heads : tails; 8 | } 9 | 10 | static doRandom(min, max, precision) { 11 | function rand(min, max) { 12 | return lerp(Math.random(), min, max); 13 | } 14 | 15 | function lerp(ratio, start, end) { 16 | return start + (end - start) * ratio; 17 | } 18 | 19 | if (typeof precision == 'number') { 20 | var p = Math.pow(10, precision); 21 | return Math.round(rand(min, max) * p) / p; 22 | } else { 23 | return Math.round(rand(min - 0.5, max + 0.5)); 24 | } 25 | } 26 | 27 | static loadShader(name) { 28 | return new Promise((resolve, reject) => { 29 | Promise.all([fetch(`shaders/${name}.vs`), fetch(`shaders/${name}.fs`)]).then(data => { 30 | let vs, fs; 31 | data.forEach(response => { 32 | if (response.url.indexOf('vs') > -1) vs = response.text(); 33 | else fs = response.text(); 34 | }); 35 | 36 | Promise.all([vs, fs]).then(data => { 37 | vs = data[0]; 38 | fs = data[1]; 39 | 40 | resolve({vs, fs}); 41 | }); 42 | }) 43 | 44 | }); 45 | } 46 | 47 | static loadGeometry(name) { 48 | return new Promise((resolve, reject) => { 49 | fetch(`geometry/${name}.json`).then(response => { 50 | response.text().then(text => { 51 | let loader = new THREE.BufferGeometryLoader(); 52 | let geom = loader.parse(JSON.parse(text)); 53 | console.log(geom); 54 | resolve(geom); 55 | }); 56 | }) 57 | 58 | }); 59 | } 60 | 61 | static range(oldValue, oldMin, oldMax, newMin, newMax, clamped) { 62 | let oldRange = (oldMax - oldMin); 63 | let newRange = (newMax - newMin); 64 | let newValue = (((oldValue - oldMin) * newRange) / oldRange) + newMin; 65 | if (clamped) return _this.clamp(newValue, Math.min(newMin, newMax), Math.max(newMin, newMax)); 66 | return newValue; 67 | } 68 | } 69 | 70 | class ShaderUIL { 71 | constructor(mat) { 72 | this.group = window.uil.add('group', {name: location.hash.slice(1)}); 73 | this.group.open(); 74 | 75 | for (var key in mat.uniforms) { 76 | let obj = mat.uniforms[key]; 77 | switch (obj.type) { 78 | case 'f': this.createNumber(obj, key); break; 79 | case 'c': this.createColor(obj, key); break; 80 | } 81 | } 82 | } 83 | 84 | createNumber(obj, key) { 85 | let params = { 86 | name: key, 87 | type: 'html', 88 | value: obj.value, 89 | callback: val => { 90 | obj.value = val; 91 | } 92 | }; 93 | 94 | this.group.add('number', params); 95 | } 96 | 97 | createColor(obj, key) { 98 | let params = { 99 | name: key, 100 | type: 'html', 101 | value: obj.value.getHex(), 102 | callback: val => { 103 | if (Array.isArray(val)) obj.value.setRGB(val[0], val[1], val[2]); 104 | else obj.value.set(val); 105 | } 106 | }; 107 | 108 | this.group.add('color', params); 109 | } 110 | 111 | static push(mat) { 112 | new ShaderUIL(mat); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /js/elements/Gem.js: -------------------------------------------------------------------------------- 1 | class Gem { 2 | constructor() { 3 | this.group = new THREE.Group(); 4 | 5 | Utils.loadShader('Gem').then(obj => { 6 | let geom = new THREE.TetrahedronGeometry(1.5, 0); 7 | this.mat = this.getShader(obj.vs, obj.fs); 8 | let mesh = new THREE.Mesh(geom, this.mat); 9 | this.group.add(mesh); 10 | 11 | ShaderUIL.push(this.mat); 12 | }); 13 | } 14 | 15 | getShader(vs, fs) { 16 | let uniforms = { 17 | lightColor: {type: 'c', value: new THREE.Color(0xA06CD5)}, 18 | strength: { type: 'f', value: 1.1 }, 19 | shininess: { type: 'f', value: 1 }, 20 | radius: { type: 'f', value: 1 }, 21 | time: { type: 'f', value: 1 }, 22 | LTPower: { type: 'f', value: 0 }, 23 | LTScale: { type: 'f', value: 0.2 }, 24 | LTDistortion: { type: 'f', value: 0 }, 25 | LTAmbient: { type: 'f', value: 1 }, 26 | darkness: {type: 'f', value: 0} 27 | }; 28 | 29 | let shader = new THREE.ShaderMaterial({ 30 | vertexShader: vs, 31 | fragmentShader: fs, 32 | uniforms 33 | }); 34 | 35 | // shader.wireframe = true; 36 | 37 | return shader; 38 | } 39 | 40 | update() { 41 | if (this.mat) { 42 | this.mat.uniforms.time.value = performance.now() * 0.00025; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /js/elements/Sky.js: -------------------------------------------------------------------------------- 1 | class Sky { 2 | constructor() { 3 | this.group = new THREE.Group(); 4 | 5 | Utils.loadShader('Sky').then(obj => { 6 | let geom = new THREE.IcosahedronGeometry(100, 4); 7 | this.mat = this.getShader(obj.vs, obj.fs); 8 | let mesh = new THREE.Mesh(geom, this.mat); 9 | this.group.add(mesh); 10 | 11 | ShaderUIL.push(this.mat); 12 | }); 13 | } 14 | 15 | getShader(vs, fs) { 16 | let uniforms = { 17 | time: {type: 'f', value: 0}, 18 | sat: {type: 'f', value: 0}, 19 | color: {type: 'c', value: new THREE.Color(0x49BEAA)} 20 | }; 21 | 22 | let shader = new THREE.ShaderMaterial({ 23 | vertexShader: vs, 24 | fragmentShader: fs, 25 | uniforms 26 | }); 27 | 28 | shader.side = THREE.BackSide; 29 | 30 | return shader; 31 | } 32 | 33 | update() { 34 | if (this.mat) { 35 | this.mat.uniforms.time.value = performance.now() * 0.000025; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /js/elements/Terrain.js: -------------------------------------------------------------------------------- 1 | class Terrain { 2 | constructor() { 3 | this.group = new THREE.Group(); 4 | 5 | Promise.all([Utils.loadShader('Terrain'), this.loadGeometry()]).then(data => { 6 | let obj = data[0]; 7 | let geom = data[1]; 8 | this.mat = this.getShader(obj.vs, obj.fs); 9 | let mesh = new THREE.Mesh(geom, this.mat); 10 | this.group.add(mesh); 11 | 12 | ShaderUIL.push(this.mat); 13 | }); 14 | } 15 | 16 | loadGeometry() { 17 | return new Promise((resolve, reject) => { 18 | Utils.loadGeometry('plane').then(geom => { 19 | geom.scale(0.12, 0.12, 0.12); 20 | geom.translate(0, 6, 0); 21 | 22 | geom.computeBoundingBox(); 23 | 24 | let posArray = geom.attributes.position.array; 25 | let uvArray = geom.attributes.uv.array; 26 | let count = geom.attributes.uv.count; 27 | for (let i = 0; i < count; i++) { 28 | let x = posArray[i * 3 + 0]; 29 | let z = posArray[i * 3 + 2]; 30 | let u = Utils.range(x, geom.boundingBox.min.x, geom.boundingBox.max.x, 0, 1); 31 | let v = Utils.range(z, geom.boundingBox.min.z, geom.boundingBox.max.z, 0, 1); 32 | uvArray[i * 2 + 0] = u; 33 | uvArray[i * 2 + 1] = v; 34 | } 35 | 36 | resolve(geom); 37 | }); 38 | }); 39 | } 40 | 41 | getShader(vs, fs) { 42 | let uniforms = { 43 | time: {type: 'f', value: 0}, 44 | transition: {type: 'f', value: 1}, 45 | transHeight: {type: 'f', value: 1}, 46 | transDirection: {type: 'f', value: 1}, 47 | baseColor: {type: 'c', value: new THREE.Color(0xfef0ff)}, 48 | multiplyColor: {type: 'c', value: new THREE.Color(0xead4ed)}, 49 | lightPos: {type: 'v3', value: new THREE.Vector3(100, 100, 0)}, 50 | lightColor: {type: 'c', value: new THREE.Color(0xfff9e6)} 51 | }; 52 | 53 | let shader = new THREE.ShaderMaterial({ 54 | vertexShader: vs, 55 | fragmentShader: fs, 56 | uniforms 57 | }); 58 | 59 | shader.extensions.derivatives = true; 60 | 61 | // shader.wireframe = true; 62 | 63 | return shader; 64 | } 65 | 66 | update() { 67 | if (this.mat) { 68 | this.mat.uniforms.time.value = performance.now() * 0.00025; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/uil.min.js: -------------------------------------------------------------------------------- 1 | 'use strict';var UMC=UMC||function(){var a=document,b=a.getElementsByTagName("head")[0],c="height width top left bottom right margin-left margin-right margin-top margin-bottom".split(" "),d="pattern defs transform stop animate radialGradient linearGradient animateMotion".split(" "),e="rect circle path polygon text g line foreignObject".split(" "),f=new Image,h=a.createDocumentFragment();UMC=function(){};UMC.frag=function(){return h};UMC.setSvg=function(a,b,c,d){-1===d?a.setAttributeNS(null,b,c):a.childNodes[d|| 2 | 0].setAttributeNS(null,b,c)};UMC.setDom=function(a,b,d){var e=-1!==c.indexOf(b)?"px":"";a.style[b]=d+e};UMC.clear=function(a){for(UMC.purge(a);a.firstChild;)a.firstChild.firstChild&&UMC.clear(a.firstChild),a.removeChild(a.firstChild)};UMC.purge=function(a){var b=a.attributes,c,d;if(b)for(c=b.length;c--;)d=b[c].name,"function"===typeof a[d]&&(a[d]=null);if(b=a.childNodes)for(c=b.length;c--;)UMC.purge(a.childNodes[c])};UMC.dom=function(b,c,k,h,f,m){c=c||"div";-1!==d.indexOf(c)||-1!==e.indexOf(c)?(void 0=== 3 | f&&(f=a.createElementNS("http://www.w3.org/2000/svg","svg")),UMC.add(f,c,h,m)):f=void 0===f?a.createElementNS("http://www.w3.org/1999/xhtml",c):f.appendChild(a.createElementNS("http://www.w3.org/1999/xhtml",c));b&&("UIL"===b?k="-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;"+k:"UIL text"===b?k='-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;font-family:"Lucida Console", Monaco, monospace; font-size:11px; color:#CCC; padding:2px 10px; left:0; top:2px; height:16px; width:100px; overflow:hidden; white-space: nowrap;'+ 4 | k:"UIL textSelect"===b?k='-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;font-family:"Lucida Console", Monaco, monospace; font-size:11px; color:#CCC; padding:2px 10px; left:0; top:2px; height:16px; width:100px; overflow:hidden; white-space: nowrap;pointer-events:auto; padding:2px 5px; outline:none; -webkit-appearance:none; -moz-appearance:none; border:1px dashed #4f4f4f; -ms-user-select:element;'+ 5 | k:"UIL number"===b?k='-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none;position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; overflow:hidden; background:none;font-family:"Lucida Console", Monaco, monospace; font-size:11px; color:#CCC; padding:2px 10px; left:0; top:2px; height:16px; width:100px; overflow:hidden; white-space: nowrap;letter-spacing:-1px; padding:2px 5px;'+ 6 | k:f.setAttribute("class",b));k&&(f.style.cssText=k);return void 0===m?f:f.childNodes[m||0]};UMC.cc=function(c,d,e){e=void 0===e?".":"";"*"===c&&(e="");var f=a.createElement("style");f.type="text/css";b.appendChild(f);(f.sheet||{}).insertRule?f.sheet.insertRule(e+c+"{"+d+"}",0):(f.styleSheet||f.sheet).addRule(e+c,d)};UMC.clone=function(a,b){void 0===b&&(b=!0);return a.cloneNode(b)};UMC.add=function(a,b,c,d){var f=document.createElementNS("http://www.w3.org/2000/svg",b);this.set(f,c);this.get(a,d).appendChild(f); 7 | -1!==e.indexOf(b)&&(f.style.pointerEvents="none");return f};UMC.set=function(a,b){for(var c in b)"txt"===c&&(a.textContent=b[c]),a.setAttributeNS(null,c,b[c])};UMC.get=function(a,b){if(void 0===b)return a;if(!isNaN(b))return a.childNodes[b];if(b instanceof Array){if(2===b.length)return a.childNodes[b[0]].childNodes[b[1]];if(3===b.length)return a.childNodes[b[0]].childNodes[b[1]].childNodes[b[2]]}};UMC.toCanvas=function(a,b,c,d){var e=a.getContext("2d");a=null;"string"===typeof b?(a=UMC.dom(null,"iframe", 8 | "position:abolute; left:0; top:0; width:"+c+"px; height:"+d+"px;"),a.src=b):(a=b.cloneNode(!0),a.style.left=0);b=UMC.dom(null,"foreignObject","position:abolute; left:0; top:0;",{width:c,height:d});b.childNodes[0].appendChild(a);b.setAttribute("version","1.1");b.setAttribute("xmlns","http://www.w3.org/2000/svg");b.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");b.setAttribute("width",c);b.setAttribute("height",d);b.childNodes[0].setAttribute("width","100%");b.childNodes[0].setAttribute("height", 9 | "100%");b="data:image/svg+xml;base64,"+window.btoa((new XMLSerializer).serializeToString(b));a=null;f.src=b;setTimeout(function(){e.clearRect(0,0,c,d);e.drawImage(f,0,0,c,d,0,0,c,d)},0)};return UMC}();var define,module,exports,performance,UIL=function(){UIL={REVISION:1,frag:UMC.frag,DOM:UMC.dom,clear:UMC.clear,setSvg:UMC.setSvg,isLoop:!1,listens:[],main:null,DEF:!1,WIDTH:240,HEIGHT:20,P:30,BASIC:"-o-user-select:none; -ms-user-select:none; -khtml-user-select:none; -webkit-user-select:none; -moz-user-select:none; position:absolute; pointer-events:none; box-sizing:border-box; margin:0; padding:0; border:none; background:none;",COLOR:"N",BASECOLOR:"#C0C0C0",BUTTON:"#404040",BOOLBG:"#181818",SELECT:"#308AFF", 10 | MOVING:"#03afff",SELECTDOWN:"#024699",BG:"rgba(0,0,0,0.3)",SVGB:"rgba(0,0,0,0.3)",SVGC:"rgba(120,120,120,0.6)",Border:"#4f4f4f",BorderSelect:"#308AFF",setText:function(a,b,c){UIL.TXT=UIL.BASIC+"font-family:"+(c||'"Consolas", "Lucida Console", Monaco, monospace')+"; font-size:"+(a||11)+"px; color:"+(b||"#CCC")+"; padding:2px 10px; left:0; top:2px; height:16px; width:100px; overflow:hidden; white-space: nowrap;";UIL.TXTSELECT=UIL.TXT+"pointer-events:auto; padding:2px 5px; outline:none; -webkit-appearance:none; -moz-appearance:none; border:1px dashed "+ 11 | UIL.Border+"; -ms-user-select:element;";UIL.NUM=UIL.TXT+"letter-spacing:-1px; padding:2px 5px;";UIL.ITEM=UIL.TXT+"position:relative; background:rgba(0,0,0,0.2); margin-bottom:1px; pointer-events:auto; cursor:pointer;"},GPATH:"M 7 7 L 7 8 8 8 8 7 7 7 M 5 7 L 5 8 6 8 6 7 5 7 M 3 7 L 3 8 4 8 4 7 3 7 M 7 5 L 7 6 8 6 8 5 7 5 M 6 6 L 6 5 5 5 5 6 6 6 M 7 3 L 7 4 8 4 8 3 7 3 M 6 4 L 6 3 5 3 5 4 6 4 M 3 5 L 3 6 4 6 4 5 3 5 M 3 3 L 3 4 4 4 4 3 3 3 Z"};UIL.setText();return UIL}(); 12 | (function(a){"function"===typeof define&&define.amd?define("uil",UIL):"undefined"!==typeof exports&&"undefined"!==typeof module?module.exports=UIL:a.UIL=UIL})(this);UIL.loop=function(){UIL.isLoop&&requestAnimationFrame(UIL.loop);UIL.update()};UIL.update=function(){for(var a=UIL.listens.length;a--;)UIL.listens[a].listening()};UIL.removeListen=function(a){a=UIL.listens.indexOf(a);UIL.listens.splice(a,1);0===UIL.listens.length&&(UIL.isLoop=!1)};UIL.addListen=function(a){-1===UIL.listens.indexOf(a)&&(UIL.listens.push(a),UIL.isLoop||(UIL.isLoop=!0,UIL.loop()))}; 13 | UIL.add=function(){var a=arguments,b,c,d=!1;"string"===typeof a[0]?(b=a[0][0].toUpperCase()+a[0].slice(1),c=a[1]||{}):"object"===typeof a[0]&&(d=!0,void 0===a[2]&&[].push.call(a,{}),b=UIL.autoType.apply(this,a),c=a[2],c.name=a[1],c.value=a[0][a[1]]);b=new UIL[b](c);d&&b.setReferency(a[0],a[1]);return b};UIL.autoType=function(){var a=arguments,b="Slide";a[2].type&&(b=a[2].type);return b}; 14 | UIL.ColorLuma=function(a,b){a=String(a).replace(/[^0-9a-f]/gi,"");6>a.length&&(a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]);b=b||0;var c="#",d,e;for(e=0;3>e;e++)d=parseInt(a.substr(2*e,2),16),d=Math.round(Math.min(Math.max(0,d+d*b),255)).toString(16),c+=("00"+d).substr(d.length);return c};UIL.findDeepInver=function(a){return 0.6>=0.3*a[0]+0.59*a[1]+0.11*a[2]};UIL.hexToHtml=function(a){return"#"+("000000"+(void 0===a?0:a).toString(16)).substr(-6)};UIL.htmlToHex=function(a){return a.toUpperCase().replace("#","0x")}; 15 | UIL.u255=function(a,b){return parseInt(a.substring(b,b+2),16)/255};UIL.u16=function(a,b){return parseInt(a.substring(b,b+1),16)/15};UIL.unpack=function(a){if(7==a.length)return[UIL.u255(a,1),UIL.u255(a,3),UIL.u255(a,5)];if(4==a.length)return[UIL.u16(a,1),UIL.u16(a,2),UIL.u16(a,3)]};UIL.htmlRgb=function(a){return"rgb("+Math.round(255*a[0])+","+Math.round(255*a[1])+","+Math.round(255*a[2])+")"};UIL.rgbToHex=function(a){return"#"+("000000"+(255*a[0]<<16^255*a[1]<<8^255*a[2]<<0).toString(16)).slice(-6)}; 16 | UIL.hueToRgb=function(a,b,c){0>c&&(c+=1);1c?b:c<2/3?a+6*(b-a)*(2/3-c):a};UIL.rgbToHsl=function(a){var b=a[0],c=a[1];a=a[2];var d=Math.min(b,c,a),e=Math.max(b,c,a),f=e-d,h=0,g=0,d=(d+e)/2;0d&&(g=f/(0.5>d?2*d:2-2*d));0=a?a*(b+1):a+b-a*b;a=2*a-b;return[UIL.hueToRgb(a,b,c+0.33333),UIL.hueToRgb(a,b,c),UIL.hueToRgb(a,b,c-0.33333)]};UIL.Gui=function(a){a=a||{};void 0!==a.Tpercent&&(UIL.P=a.Tpercent);void 0===a.css&&(a.css="");this.height=20;this.width=void 0!==a.width?a.width:UIL.WIDTH;this.width=void 0!==a.size?a.size:this.width;this.left=0;this.top=a.top||0;this.h=0;this.prevY=-1;this.isWithClose=!0;this.bh=a.bh||20;void 0!==a.close&&(this.bh=(this.isWithClose=a.close)?this.bh:0);this.sw=a.sw||10;UIL.main=this;this.callback=void 0===a.callback?null:a.callback;this.color=a.color||UIL.COLOR;this.bg=a.bg||"rgba(44,44,44,0.3)"; 18 | this.isCenter=a.center||!1;this.onWheel=this.lockwheel=!1;this.isOpen=!0;this.uis=[];this.content=UIL.DOM(null,"div",UIL.BASIC+"display:block; width:"+this.width+"px; height:auto; top:0; right:10px; transition:height 0.1s ease-out;"+a.css);document.body.appendChild(this.content);this.innerContent=UIL.DOM(null,"div",UIL.BASIC+"width:100%; top:0; left:0; height:auto;overflow:hidden;");this.content.appendChild(this.innerContent);this.inner=UIL.DOM(null,"div",UIL.BASIC+"width:100%; top:0; left:0; height:auto;"); 19 | this.innerContent.appendChild(this.inner);this.inner.name="inner";this.scrollBG=UIL.DOM(null,"div",UIL.BASIC+"right:0; top:0; width:10px; height:10px; cursor:s-resize; pointer-events:auto; display:none;");this.content.appendChild(this.scrollBG);this.scrollBG.name="scroll";this.scroll=UIL.DOM(null,"div",UIL.BASIC+"background:#666; right:0; top:0; width:5px; height:10px;");this.scrollBG.appendChild(this.scroll);this.bottom=UIL.DOM(null,"div",UIL.TXT+"width:100%; top:auto; bottom:0; left:0; border-bottom-right-radius:10px; border-bottom-left-radius:10px; text-align:center; pointer-events:auto; cursor:pointer; height:"+ 20 | this.bh+"px; line-height:"+(this.bh-5)+"px;");this.content.appendChild(this.bottom);this.bottom.textContent="close";this.bottom.name="bottom";this.bottom.style.background=this.bg;this.isScroll=this.isDown=!1;this.callbackClose=function(){};this.content.addEventListener("mousedown",this,!1);this.content.addEventListener("mousemove",this,!1);this.content.addEventListener("mouseout",this,!1);this.content.addEventListener("mouseup",this,!1);this.content.addEventListener("mouseover",this,!1);document.addEventListener("mousewheel", 21 | function(a){this.wheel(a)}.bind(this),!1);window.addEventListener("resize",function(a){this.resize(a)}.bind(this),!1);this.setWidth(this.width)}; 22 | UIL.Gui.prototype={constructor:UIL.Gui,hide:function(a){this.content.style.display=a?"none":"block"},setBG:function(a){this.bg=a;for(var b=this.uis.length;b--;)this.uis[b].setBG(a);this.bottom.style.background=a},getHTML:function(){return this.content},onChange:function(a){this.callback=a;return this},handleEvent:function(a){switch(a.type){case "mousedown":this.down(a);break;case "mouseout":this.out(a);break;case "mouseover":this.over(a);break;case "mouseup":this.up(a);break;case "mousemove":this.move(a)}}, 23 | down:function(a){a.target.name&&("scroll"===a.target.name&&(this.isDown=!0,this.move(a),document.addEventListener("mouseup",this,!1),document.addEventListener("mousemove",this,!1)),"bottom"===a.target.name&&(this.isOpen=this.isOpen?!1:!0,this.bottom.textContent=this.isOpen?"close":"open",this.testHeight()))},move:function(a){this.isDown&&(this.scroll.style.background="#AAA",this.update(a.clientY-this.top-0.5*this.sh))},out:function(a){a.target.name&&("scroll"===a.target.name&&(this.scroll.style.background= 24 | "#666"),"bottom"===a.target.name&&(this.bottom.style.color="#CCC"))},up:function(a){this.isDown=!1;this.scroll.style.background="#666";document.removeEventListener("mouseup",this,!1);document.removeEventListener("mousemove",this,!1)},over:function(a){a.target.name&&("scroll"===a.target.name&&(this.scroll.style.background="#888"),"bottom"===a.target.name&&(this.bottom.style.color="#FFF"))},wheel:function(a){if(!this.lockwheel&&this.isScroll){var b=a.clientX,c=this.content.getBoundingClientRect().left; 25 | bc+this.width||(b=0,a.wheelDeltaY?b=0.04*-a.wheelDeltaY:a.wheelDelta?b=0.2*-a.wheelDelta:a.detail&&(b=4*a.detail),this.py+=b,this.update(this.py))}},add:function(){var a=arguments;"object"===typeof a[1]?(a[1].isUI=!0,a[1].main=this):"string"===typeof a[1]&&(void 0===a[2]?[].push.call(a,{isUI:!0,main:this}):(a[2].isUI=!0,a[2].main=this));a=UIL.add.apply(this,a);this.uis.push(a);a.py=this.h;if(a.autoWidth)this.prevY=-1,this.calc(a.h+1);else{var b=a.c[0].getBoundingClientRect().top;this.prevY!== 26 | b&&(this.calc(a.h+1),this.prevY=b)}return a},remove:function(a){a=this.uis.indexOf(a);-1!==a&&this.uis[a].clear()},clearOne:function(a){a=this.uis.indexOf(a);-1!==a&&(this.inner.removeChild(this.uis[a].c[0]),this.uis.splice(a,1))},clear:function(){for(var a=this.uis.length;a--;)this.uis[a].clear();this.uis=[];UIL.listens=[];this.calc(-this.h)},update:function(a){a=0>a?0:a;a=a>this.range?this.range:a;this.inner.style.top=-~~(a/this.ratio)+"px";this.scroll.style.top=~~a+"px";this.py=a},showScroll:function(a){this.isScroll= 27 | !0;this.total=this.h;this.maxView=this.maxHeight;this.ratio=this.maxView/this.total;this.sh=this.maxView*this.ratio;20>this.sh&&(this.sh=20);this.range=this.maxView-this.sh;this.scrollBG.style.display="block";this.scrollBG.style.height=this.maxView+"px";this.scroll.style.height=this.sh+"px";this.update(0)},hideScroll:function(){this.isScroll=!1;this.update(0);this.scrollBG.style.display="none"},resize:function(a){this.testHeight()},calc:function(a){this.h+=a;clearTimeout(this.tmp);this.tmp=setTimeout(this.testHeight.bind(this), 28 | 10)},testHeight:function(){this.tmp&&clearTimeout(this.tmp);this.height=this.top+this.bh;this.isOpen?(this.maxHeight=window.innerHeight-this.top-this.bh,this.h>this.maxHeight?(this.height=this.maxHeight+this.bh,this.showScroll()):(this.height=this.h+this.bh,this.hideScroll())):this.hideScroll();this.innerContent.style.height=this.height-this.bh+"px";this.content.style.height=this.height+"px";this.bottom.style.top=this.height-this.bh+"px"},setWidth:function(a){a&&(this.width=a);this.content.style.width= 29 | this.width+"px";this.isCenter&&(this.content.style.marginLeft=-~~(0.5*this.width)+"px");for(var b=a=this.uis.length;b--;)this.uis[b].setSize(this.width);for(b=a;b--;)this.uis[b].rSize();this.resize()}};UIL.Proto=function(a){a=a||{};this.main=a.main||null;this.p=UIL.P;void 0!==a.p&&(this.p=a.p);this.autoWidth=!0;this.isGroup=!1;this.parentGroup=null;this.autoHeight=!1;this.isUI=a.isUI||!1;this.isEdit=this.mono=this.isNumber=!1;if(this.simple=a.simple||!1)this.sa=0;this.width=this.isUI?this.main.width:UIL.WIDTH;void 0!==a.width&&(this.width=a.width);void 0!==a.size&&(this.width=a.size);this.setSize(this.width);void 0!==a.sa&&(this.sa=a.sa);void 0!==a.sb&&(this.sb=a.sb);this.simple&&(this.sb=this.width- 30 | this.sa);this.sc=void 0===a.sc?47:a.sc;this.val=this.parent=null;this.isSend=!1;var b=20;this.isUI&&(b=UIL.HEIGHT);this.h=a.h||a.height||b;this.h=11>this.h?11:this.h;this.bgcolor=UIL.COLOR||a.bgcolor;this.bg=this.isUI?this.main.bg:"rgba(44,44,44,0.3)";void 0!==a.bg&&(this.bg=a.bg);this.titleColor=a.titleColor||UIL.BASECOLOR;this.fontColor=a.fontColor||UIL.BASECOLOR;this.colorPlus=UIL.ColorLuma(this.fontColor,0.3);this.txt=a.name||"Proto";this.rename=a.rename||"";this.target=a.target||null;this.callback= 31 | void 0===a.callback?null:a.callback;this.endCallback=null;null===this.callback&&this.isUI&&null!==this.main.callback&&(this.callback=this.main.callback);this.c=[];this.s=[];this.c[0]=UIL.DOM(null,"div",UIL.BASIC+"position:relative; height:20px; float:left; overflow:hidden;");this.s[0]=this.c[0].style;this.isUI&&(this.s[0].marginBottom="1px");this.simple||(this.c[1]=UIL.DOM(null,"div",UIL.TXT),this.s[1]=this.c[1].style,this.c[1].textContent=""===this.rename?this.txt:this.rename,this.s[1].color=this.titleColor); 32 | if(a.pos){this.s[0].position="absolute";for(var c in a.pos)this.s[0][c]=a.pos[c];this.mono=!0}a.css&&(this.s[0].cssText=a.css)}; 33 | UIL.Proto.prototype={constructor:UIL.Proto,init:function(){var a=this.s;a[0].height=this.h+"px";this.isUI&&(this.s[0].background=this.bg);this.autoHeight&&(this.s[0].transition="height 0.1s ease-out");void 0!==this.c[1]&&this.autoWidth&&(a[1]=this.c[1].style,a[1].height=this.h-4+"px",a[1].lineHeight=this.h-8+"px");for(var b=UIL.frag(),c=1,d=this.c.length;c!==d;c++)void 0!==this.c[c]&&(b.appendChild(this.c[c]),a[c]=this.c[c].style);null!==this.target?this.target.appendChild(this.c[0]):this.isUI?this.main.inner.appendChild(this.c[0]): 34 | document.body.appendChild(this.c[0]);this.c[0].appendChild(b);this.rSize();this.addEvent()},rename:function(a){this.c[1].textContent=a},setBG:function(a){this.bg=a;this.s[0].background=a},listen:function(){UIL.addListen(this);UIL.listens.push(this);return this},listening:function(){null!==this.parent&&(this.isSend||this.isEdit||this.setValue(this.parent[this.val]))},setValue:function(a){this.value=this.isNumber?this.numValue(a):a;this.update()},update:function(){},onChange:function(a){this.callback= 35 | a;return this},onFinishChange:function(a){this.callback=null;this.endCallback=a;return this},send:function(a){this.isSend=!0;null!==this.parent&&(this.parent[this.val]=a||this.value);this.callback&&this.callback(a||this.value);this.isSend=!1},sendEnd:function(a){this.endCallback&&this.endCallback(a||this.value);null!==this.parent&&(this.parent[this.val]=a||this.value)},clear:function(){this.clearEvent();UIL.clear(this.c[0]);null!==this.target?this.target.removeChild(this.c[0]):this.isUI?this.main.clearOne(this): 36 | document.body.removeChild(this.c[0]);this.target=this.callback=this.s=this.c=null},setSize:function(a){this.autoWidth&&(this.width=a,this.p=void 0===this.p?UIL.P:this.p,this.simple?this.sb=this.width-this.sa:(a=this.p/100*this.width,this.sa=~~a+10,this.sb=~~this.width-a-20))},rSize:function(){this.autoWidth&&(this.s[0].width=this.width+"px",this.simple||(this.s[1].width=this.sa+"px"))},setTypeNumber:function(a){this.isNumber=!0;this.value=0;void 0!==a.value&&(this.value="string"===typeof a.value? 37 | 1*a.value:a.value);this.min=void 0===a.min?-Infinity:a.min;this.max=void 0===a.max?Infinity:a.max;this.precision=void 0===a.precision?2:a.precision;var b;switch(this.precision){case 0:b=1;break;case 1:b=0.1;break;case 2:b=0.01;break;case 3:b=0.001;break;case 4:b=1E-4}this.step=void 0===a.step?b:a.step;this.range=this.max-this.min;this.value=this.numValue(this.value)},numValue:function(a){return 1*Math.min(this.max,Math.max(this.min,a)).toFixed(this.precision)},addEvent:function(){for(var a=this.c.length, 38 | b,c;a--;)if(c=this.c[a],void 0!==c&&void 0!==c.events)for(b=c.events.length;b--;)c.addEventListener(c.events[b],this,!1)},clearEvent:function(){for(var a=this.c.length,b,c;a--;)if(c=this.c[a],void 0!==c&&void 0!==c.events)for(b=c.events.length;b--;)c.removeEventListener(c.events[b],this,!1)},handleEvent:function(a){},setReferency:function(a,b){this.parent=a;this.val=b},display:function(a){this.s[0].display=a?"block":"none"}};UIL.Group=function(a){UIL.Proto.call(this,a);this.isGroup=this.autoHeight=!0;this.baseH=this.h;var b=Math.floor(0.5*this.h)-6;this.isOpen=a.open||!1;this.c[2]=UIL.DOM(null,"div",UIL.BASIC+"width:100%; left:0; height:auto; overflow:hidden; top:"+this.h+"px");this.c[3]=UIL.DOM(null,"path",UIL.BASIC+"position:absolute; width:10px; height:10px; left:0; top:"+b+"px;",{d:UIL.GPATH,fill:this.fontColor,stroke:"none"});this.c[4]=UIL.DOM(null,"path",UIL.BASIC+"position:absolute; width:10px; height:10px; left:4px; top:"+ 39 | b+"px;",{d:"M 3 8 L 8 5 3 2 3 8 Z",fill:this.fontColor,stroke:"none"});this.c[5]=UIL.DOM(null,"div",UIL.BASIC+"background:rgba(255, 255, 255, 0.2); width:100%; left:0; height:1px; bottom:0px");b=this.s;b[0].height=this.h+"px";b[1].height=this.h+"px";b[1].pointerEvents="auto";b[1].cursor="pointer";this.c[1].name="group";this.s[1].marginLeft="10px";this.s[1].lineHeight=this.h-4;this.s[1].color=this.fontColor;this.s[1].fontWeight="bold";this.uis=[];this.c[1].events=["click"];this.init();void 0!==a.bg&& 40 | this.setBG(a.bg);this.isOpen&&this.open()};UIL.Group.prototype=Object.create(UIL.Proto.prototype);UIL.Group.prototype.constructor=UIL.Group;UIL.Group.prototype.setBG=function(a){this.s[0].background=a;for(var b=this.uis.length;b--;)this.uis[b].setBG(a)};UIL.Group.prototype.handleEvent=function(a){a.preventDefault();switch(a.type){case "click":this.click(a)}};UIL.Group.prototype.click=function(a){this.isOpen?this.close():this.open()}; 41 | UIL.Group.prototype.add=function(){var a=arguments;"object"===typeof a[1]?(a[1].isUI=this.isUI,a[1].target=this.c[2]):"string"===typeof arguments[1]&&(void 0===a[2]?[].push.call(a,{isUI:!0,target:this.c[2]}):(a[2].isUI=!0,a[2].target=this.c[2]));a=UIL.Gui.prototype.add.apply(this,a);a.autoHeight&&(a.parentGroup=this);return a};UIL.Group.prototype.open=function(){this.isOpen=!0;UIL.setSvg(this.c[4],"d","M 5 8 L 8 3 2 3 5 8 Z");this.rSizeContent();this.isUI&&this.main.calc(this.h-this.baseH)}; 42 | UIL.Group.prototype.close=function(){this.isUI&&this.main.calc(-(this.h-this.baseH));this.isOpen=!1;UIL.setSvg(this.c[4],"d","M 3 8 L 8 5 3 2 3 8 Z");this.h=this.baseH;this.s[0].height=this.h+"px"};UIL.Group.prototype.clear=function(){this.clearGroup();this.isUI&&this.main.calc(-(this.h+1));UIL.Proto.prototype.clear.call(this)};UIL.Group.prototype.clearGroup=function(){this.close();for(var a=this.uis.length;a--;)this.uis[a].clear(),this.uis.pop();this.uis=[];this.h=this.baseH}; 43 | UIL.Group.prototype.calc=function(a){this.isOpen&&(void 0!==a?(this.h+=a,this.isUI&&this.main.calc(a)):this.h=this.c[2].offsetHeight+this.baseH,this.s[0].height=this.h+"px")};UIL.Group.prototype.rSizeContent=function(){for(var a=this.uis.length;a--;)this.uis[a].setSize(this.width),this.uis[a].rSize();this.calc()}; 44 | UIL.Group.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);var a=this.s;a[3].left=this.sa+this.sb-17+"px";a[1].width=this.width+"px";a[2].width=this.width+"px";this.isOpen&&this.rSizeContent()};UIL.Title=function(a){UIL.Proto.call(this,a);a=a.prefix||"";this.c[2]=UIL.DOM(null,"div",UIL.TXT+"text-align:right; width:60px; line-height:"+(this.h-8)+"px; color:"+this.fontColor);31===this.h&&(this.s[0].height=this.h+"px",this.s[1].top="8px",this.c[2].style.top="8px");this.c[1].textContent=this.txt.substring(0,1).toUpperCase()+this.txt.substring(1).replace("-"," ");this.c[2].textContent=a;this.init()};UIL.Title.prototype=Object.create(UIL.Proto.prototype);UIL.Title.prototype.constructor=UIL.Title; 45 | UIL.Title.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);this.s[1].width=this.width-50+"px";this.s[2].left=this.width-76+"px"};UIL.Title.prototype.text=function(a){this.c[1].textContent=a};UIL.Title.prototype.text2=function(a){this.c[2].textContent=a};UIL.String=function(a){UIL.Proto.call(this,a);this.value=a.value||"";this.allway=a.allway||!1;this.c[2]=UIL.DOM(null,"div",UIL.TXTSELECT);this.c[2].name="input";this.c[2].textContent=this.value;this.c[2].events=["mousedown","keydown","keyup","blur","focus"];this.init()};UIL.String.prototype=Object.create(UIL.Proto.prototype);UIL.String.prototype.constructor=UIL.String; 46 | UIL.String.prototype.handleEvent=function(a){switch(a.type){case "mousedown":this.down(a);break;case "blur":this.blur(a);break;case "focus":this.focus(a);break;case "keydown":this.keydown(a);break;case "keyup":this.keyup(a)}};UIL.String.prototype.down=function(a){a.target.contentEditable=!0;a.target.focus();a.target.style.cursor="auto"};UIL.String.prototype.blur=function(a){a.target.style.borderColor=UIL.Border;a.target.contentEditable=!1}; 47 | UIL.String.prototype.focus=function(a){a.target.style.borderColor=UIL.BorderSelect};UIL.String.prototype.keydown=function(a){a.stopPropagation();13===a.keyCode&&(a.preventDefault(),this.value=a.target.textContent,a.target.blur(),this.send())};UIL.String.prototype.keyup=function(a){a.stopPropagation();this.value=a.target.textContent;this.allway&&this.send()}; 48 | UIL.String.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);this.s[2].color=this.fontColor;this.s[2].left=this.sa+"px";this.s[2].width=this.sb+"px";this.s[2].height=this.h-4+"px";this.s[2].lineHeight=this.h-8+"px"};UIL.Number=function(a){UIL.Proto.call(this,a);this.type="number";this.setTypeNumber(a);this.allway=a.allway||!1;this.isDrag=void 0===a.drag?!0:a.drag;this.value=[0];this.toRad=1;this.isNumber=!0;this.isSelect=this.isVector=this.isAngle=!1;void 0!==a.value&&(isNaN(a.value)?a.value instanceof Array?(this.value=a.value,this.isNumber=!1):a.value instanceof Object&&(this.value=[],a.value.x&&(this.value[0]=a.value.x),a.value.y&&(this.value[1]=a.value.y),a.value.z&&(this.value[2]=a.value.z),a.value.w&&(this.value[3]= 49 | a.value.w),this.isVector=!0):this.value=[a.value]);this.length=this.value.length;a.isAngle&&(this.isAngle=!0,this.toRad=Math.PI/180);this.w=(UIL.BW+5)/this.length-5;this.current=void 0;for(var b=this.length;b--;)this.isAngle&&(this.value[b]=(180*this.value[b]/Math.PI).toFixed(this.precision)),this.c[2+b]=UIL.DOM(null,"div",UIL.TXTSELECT+"letter-spacing:-1px; cursor:pointer; height:"+(this.h-4)+"px; line-height:"+(this.h-8)+"px;"),this.c[2+b].name=b,this.isDrag&&(this.c[2+b].style.cursor="move"),a.center&& 50 | (this.c[2+b].style.textAlign="center"),this.c[2+b].textContent=this.value[b],this.c[2+b].style.color=this.fontColor,this.c[2+b].events=["keydown","keyup","mousedown","blur","focus"];this.init()};UIL.Number.prototype=Object.create(UIL.Proto.prototype);UIL.Number.prototype.constructor=UIL.Number; 51 | UIL.Number.prototype.handleEvent=function(a){switch(a.type){case "mousedown":this.down(a);break;case "keydown":this.keydown(a);break;case "keyup":this.keyup(a);break;case "blur":this.blur(a);break;case "focus":this.focus(a);break;case "mouseup":this.up(a);break;case "mousemove":this.move(a)}};UIL.Number.prototype.setValue=function(a,b){b=b||0;this.value[b]=this.numValue(a);this.c[2+b].textContent=this.value[b]}; 52 | UIL.Number.prototype.keydown=function(a){a.stopPropagation();13===a.keyCode&&(a.preventDefault(),this.testValue(parseFloat(a.target.name)),this.validate(),a.target.blur())};UIL.Number.prototype.keyup=function(a){a.stopPropagation();this.allway&&(this.testValue(parseFloat(a.target.name)),this.validate())};UIL.Number.prototype.blur=function(a){this.isSelect=!1;a.target.style.borderColor=UIL.Border;a.target.contentEditable=!1;a.target.style.cursor=this.isDrag?"move":"pointer"}; 53 | UIL.Number.prototype.focus=function(a){this.isSelect=!0;this.current=void 0;a.target.style.borderColor=UIL.BorderSelect;this.isDrag&&(a.target.style.cursor="auto")}; 54 | UIL.Number.prototype.down=function(a){this.isSelect||(a.preventDefault(),this.current=parseFloat(a.target.name),this.prev={x:a.clientX,y:a.clientY,d:0,id:this.current+2},this.prev.v=this.isNumber?parseFloat(this.value):parseFloat(this.value[this.current]),document.addEventListener("mouseup",this,!1),this.isDrag&&document.addEventListener("mousemove",this,!1))}; 55 | UIL.Number.prototype.up=function(a){a.preventDefault();document.removeEventListener("mouseup",this,!1);this.isDrag&&document.removeEventListener("mousemove",this,!1);void 0!==this.current&&this.current===parseFloat(a.target.name)&&(a.target.contentEditable=!0,a.target.focus())}; 56 | UIL.Number.prototype.move=function(a){a.preventDefault();void 0!==this.current&&(this.prev.d+=a.clientX-this.prev.x-(a.clientY-this.prev.y),this.value[this.current]=this.numValue(this.prev.v+this.prev.d*this.step),this.c[2+this.current].textContent=this.value[this.current],this.validate(),this.prev.x=a.clientX,this.prev.y=a.clientY)}; 57 | UIL.Number.prototype.testValue=function(a){if(isNaN(this.c[2+a].textContent))this.c[2+a].textContent=this.value[a];else{var b=this.numValue(this.c[2+a].textContent);this.c[2+a].textContent=b;this.value[a]=b}};UIL.Number.prototype.validate=function(){for(var a=[],b=this.length;b--;)a[b]=this.value[b]*this.toRad;this.isNumber?this.send(a[0]):this.send(a)}; 58 | UIL.Number.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);this.w=~~((this.sb+5)/this.length)-5;for(var a=this.s,b=this.length;b--;)a[2+b].left=~~(this.sa+this.w*b+5*b)+"px",a[2+b].width=this.w+"px"};UIL.Color=function(a){UIL.Proto.call(this,a);this.autoHeight=!0;this.ctype=a.ctype||"array";this.ww=this.sb;this.oldWidth=0;this.side=a.side||"down";this.holdTop=0;this.wheelWidth=0.1*this.ww;this.decal=this.h+2;this.radius=0.5*(this.ww-this.wheelWidth)-1;this.square=Math.floor(0.7*(this.radius-0.5*this.wheelWidth))-1;this.mid=Math.floor(0.5*this.ww);this.markerSize=0.3*this.wheelWidth;this.baseH=this.h;this.c[2]=UIL.DOM(null,"div",UIL.TXT+"height:"+(this.h-4)+"px;border-radius:3px; pointer-events:auto; cursor:pointer; border:1px solid "+ 59 | UIL.Border+"; line-height:"+(this.h-8)+"px;");this.s[2]=this.c[2].style;"up"===this.side&&(this.decal=5,this.s[2].top="auto",this.s[2].bottom="2px");this.c[3]=UIL.DOM(null,"div",UIL.BASIC+"display:none");this.c[4]=UIL.DOM(null,"canvas",UIL.BASIC+"display:none;");this.c[5]=UIL.DOM(null,"canvas",UIL.BASIC+"pointer-events:auto; cursor:pointer; display:none;");this.s[3]=this.c[3].style;this.s[5]=this.c[5].style;"up"===this.side&&(this.s[5].pointerEvents="none");this.c[4].width=this.c[4].height=this.ww; 60 | this.c[5].width=this.c[5].height=this.ww;this.ctxMask=this.c[4].getContext("2d");this.ctxOverlay=this.c[5].getContext("2d");this.ctxMask.translate(this.mid,this.mid);this.ctxOverlay.translate(this.mid,this.mid);this.hsl=null;this.value="#ffffff";void 0!==a.value&&(a.value instanceof Array?this.value=UIL.rgbToHex(a.value):isNaN(a.value)?this.value=a.value:this.value=UIL.hexToHtml(a.value));this.bcolor=null;this.isShow=this.isDown=!1;this.c[2].events=["click"];this.c[5].events=["mousedown","mousemove", 61 | "mouseup","mouseout"];this.setColor(this.value);this.init()};UIL.Color.prototype=Object.create(UIL.Proto.prototype);UIL.Color.prototype.constructor=UIL.Color;UIL.Color.prototype.handleEvent=function(a){a.preventDefault();a.stopPropagation();switch(a.type){case "click":this.click(a);break;case "mousedown":this.down(a);break;case "mousemove":this.move(a);break;case "mouseup":this.up(a);break;case "mouseout":this.out(a)}};UIL.Color.prototype.click=function(a){this.isShow?this.hide():this.show()}; 62 | UIL.Color.prototype.up=function(a){this.isDown=!1};UIL.Color.prototype.out=function(a){this.hide()};UIL.Color.prototype.down=function(a){if(this.isShow)return this.isDown=!0,this.move(a),!1}; 63 | UIL.Color.prototype.move=function(a){if(this.isDown){this.offset=this.c[5].getBoundingClientRect();var b=a.pageX-this.offset.left-this.mid;a=a.pageY-this.offset.top-this.mid;(this.circleDrag=Math.max(Math.abs(b),Math.abs(a))>this.square+2)?(b=Math.atan2(b,-a)/6.28,this.setHSL([(b+1)%1,this.hsl[1],this.hsl[2]])):(b=Math.max(0,Math.min(1,-(b/this.square*0.5)+0.5)),a=Math.max(0,Math.min(1,-(a/this.square*0.5)+0.5)),this.setHSL([this.hsl[0],b,a]))}}; 64 | UIL.Color.prototype.redraw=function(){this.oldWidth=this.ww;this.drawCircle();this.drawMask();this.drawMarkers()}; 65 | UIL.Color.prototype.show=function(){this.oldWidth!==this.ww&&this.redraw();this.isShow=!0;this.h=this.ww+this.baseH+10;this.s[0].height=this.h+"px";"up"==this.side&&(this.holdTop=1*this.s[0].top.substring(0,this.s[0].top.length-2)||"auto",isNaN(this.holdTop)||(this.s[0].top=this.holdTop-(this.h-20)+"px"),setTimeout(function(){this.s[5].pointerEvents="auto"}.bind(this),100));this.s[3].display="block";this.s[4].display="block";this.s[5].display="block";null!==this.parentGroup?this.parentGroup.calc(this.h- 66 | this.baseH):this.isUI&&this.main.calc(this.h-this.baseH)};UIL.Color.prototype.hide=function(){null!==this.parentGroup?this.parentGroup.calc(-(this.h-this.baseH)):this.isUI&&this.main.calc(-(this.h-this.baseH));this.isShow=!1;this.h=this.baseH;"up"===this.side&&(isNaN(this.holdTop)||(this.s[0].top=this.holdTop+"px"),this.s[5].pointerEvents="none");this.s[0].height=this.h+"px";this.s[3].display="none";this.s[4].display="none";this.s[5].display="none"}; 67 | UIL.Color.prototype.update=function(a){this.s[3].background=UIL.rgbToHex(UIL.hslToRgb([this.hsl[0],1,0.5]));this.drawMarkers();this.value=this.bcolor;this.s[2].background=this.bcolor;this.c[2].textContent=UIL.htmlToHex(this.bcolor);this.invert=UIL.findDeepInver(this.rgb);this.s[2].color=this.invert?"#fff":"#000";a&&("array"===this.ctype&&this.send(this.rgb),"rgb"===this.ctype&&this.send(UIL.htmlRgb(this.rgb)),"hex"===this.ctype&&this.send(UIL.htmlToHex(this.value)),"html"===this.ctype&&this.send())}; 68 | UIL.Color.prototype.setColor=function(a){var b=UIL.unpack(a);this.bcolor!=a&&b&&(this.bcolor=a,this.rgb=b,this.hsl=UIL.rgbToHsl(this.rgb),this.update());return this};UIL.Color.prototype.setHSL=function(a){this.hsl=a;this.rgb=UIL.hslToRgb(a);this.bcolor=UIL.rgbToHex(this.rgb);this.update(!0);return this};UIL.Color.prototype.calculateMask=function(a,b,c){for(var d=1/a,e=1/b,f=0;f<=b;++f)for(var h=1-f*e,g=0;g<=a;++g){var l=1-g*d,l=1-2*Math.min(h*l,(1-h)*l);c(g,f,0=k;++k)l=k/24,a=l*Math.PI*2,b=[Math.sin(e),-Math.cos(e),Math.sin(a),-Math.cos(a)],h=0.5*(e+a),g=1/Math.cos(0.5*(a-e)),e=Math.sin(h)*g,h=-Math.cos(h)*g,l=UIL.rgbToHex(UIL.hslToRgb([l,1,0.5])),0=this.step||a<=this.step)a=~~(a/this.step),this.value=this.numValue(this.old+a*this.step),this.update(!0),this.old=this.value};UIL.Slide.prototype.update=function(a){var b=(this.value-this.min)/this.range*this.w;3!==this.stype&&(this.s[5].width=~~b+"px");this.s[6]&&(this.s[6].left=~~(this.sa+b+3)+"px");this.c[2].textContent=this.value;a&&this.send()}; 82 | UIL.Slide.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);var a=this.sb-this.sc;this.w=a-6;var b=this.sc;if(this.isUI||!this.simple)b=this.sc+10;var c=~~(0.5*this.h)-8,d=this.s;d[2].width=this.sc-2+"px";d[2].left=this.width-b+2+"px";d[2].top=c+"px";d[3].left=this.sa+"px";d[3].width=a+"px";d[4].left=this.sa+"px";d[4].width=a+"px";d[5].left=this.sa+3+"px";this.update()}; 83 | UIL.Slide.prototype.validate=function(a){isNaN(this.c[2].textContent)?this.c[2].textContent=this.value:(this.value=this.numValue(this.c[2].textContent),this.update(!0))};UIL.Slide.prototype.textdown=function(a){a.target.contentEditable=!0;a.target.focus();this.isEdit=!0};UIL.Slide.prototype.keydown=function(a){a.stopPropagation();13===a.keyCode&&(a.preventDefault(),this.validate(),a.target.blur())};UIL.Slide.prototype.keyup=function(a){a.stopPropagation();this.allway&&this.validate()}; 84 | UIL.Slide.prototype.blur=function(a){a.target.style.border="none";this.isEdit=a.target.contentEditable=!1};UIL.Slide.prototype.focus=function(a){a.target.style.border="1px dashed "+UIL.BorderSelect};UIL.List=function(a){UIL.Proto.call(this,a);this.autoHeight=!0;var b=a.align||"center";this.buttonColor=UIL.BUTTON;var c=Math.floor(0.5*this.h)-5;this.c[2]=UIL.DOM(null,"div",UIL.BASIC+"top:0; height:90px; cursor:s-resize; pointer-events:auto; display:none; overflow:hidden; border:1px solid "+UIL.Border+";");this.c[3]=UIL.DOM(null,"div",UIL.TXT+UIL.BASIC+"text-align:"+b+"; line-height:"+(this.h-4)+"px; border:1px solid "+UIL.Border+"; top:1px; pointer-events:auto; cursor:pointer; background:"+this.buttonColor+ 85 | "; height:"+(this.h-2)+"px;");this.c[4]=UIL.DOM(null,"path",UIL.BASIC+"position:absolute; width:10px; height:10px; top:"+c+"px;",{d:"M 3 8 L 8 5 3 2 3 8 Z",fill:this.fontColor,stroke:"none"});this.scroller=UIL.DOM(null,"div",UIL.BASIC+"right:5px; width:10px; pointer-events:none; background:#666; display:none;");this.c[2].name="list";this.c[3].name="title";this.c[3].style.color=this.fontColor;this.c[2].events="mousedown mousemove mouseup mousewheel mouseout mouseover".split(" ");this.c[3].events= 86 | ["mousedown","mouseover","mouseout"];this.list=a.list||[];this.baseH=this.h;this.isShow=!1;this.itemHeight=a.itemHeight||this.h-3;this.full=a.full||!1;this.py=0;this.w=this.sb;this.isDown=this.scroll=!1;this.side=a.side||"down";this.holdTop=0;"up"===this.side?(this.c[2].style.top="auto",this.c[3].style.top="auto",this.c[4].style.top="auto",this.c[2].style.bottom=this.h-2+"px",this.c[3].style.bottom="1px",this.c[4].style.bottom=c+"px"):this.c[2].style.top=this.h-2+"px";this.listIn=UIL.DOM(null,"div", 87 | UIL.BASIC+"left:0; top:0; width:100%; background:rgba(0,0,0,0.2);");this.listIn.name="list";this.c[2].appendChild(this.listIn);this.c[2].appendChild(this.scroller);this.setList(this.list,a.value);this.init()};UIL.List.prototype=Object.create(UIL.Proto.prototype);UIL.List.prototype.constructor=UIL.List;UIL.List.prototype.clearList=function(){for(;this.listIn.children.length;)this.listIn.removeChild(this.listIn.lastChild)}; 88 | UIL.List.prototype.setList=function(a,b){this.clearList();this.list=a;this.length=this.list.length;this.maxItem=this.full?this.length:5;this.maxItem=this.lengththis.maxHeight&& 89 | (this.w=this.sb-20,this.scroll=!0);for(var c,d,e=0;ea?0:a,a=a>this.range?this.range:a,this.listIn.style.top=-Math.floor(a/this.ratio)+"px",this.scroller.style.top=Math.floor(a)+"px",this.py=a)}; 95 | UIL.List.prototype.listShow=function(){document.addEventListener("click",this,!1);this.update(0);this.isShow=!0;this.h=this.maxHeight+this.baseH+10;this.scroll?this.scroller.style.display="block":(this.h=this.baseH+10+this.max,this.scroller.style.display="none");this.s[0].height=this.h+"px";this.s[2].display="block";"up"===this.side?UIL.setSvg(this.c[4],"d","M 5 2 L 2 7 8 7 5 2 Z"):UIL.setSvg(this.c[4],"d","M 5 8 L 8 3 2 3 5 8 Z");this.rSizeContent();null!==this.parentGroup?this.parentGroup.calc(this.h- 96 | this.baseH):this.isUI&&this.main.calc(this.h-this.baseH)};UIL.List.prototype.listHide=function(){document.removeEventListener("click",this,!1);null!==this.parentGroup?this.parentGroup.calc(-(this.h-this.baseH)):this.isUI&&this.main.calc(-(this.h-this.baseH));this.isShow=!1;this.h=this.baseH;this.s[0].height=this.h+"px";this.s[2].display="none";UIL.setSvg(this.c[4],"d","M 3 8 L 8 5 3 2 3 8 Z")};UIL.List.prototype.text=function(a){this.c[3].textContent=a}; 97 | UIL.List.prototype.rSizeContent=function(){for(var a=this.length;a--;)this.listIn.children[a].style.width=this.w+"px"};UIL.List.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);var a=this.s,b=this.sb,c=this.sa;a[2].width=b+"px";a[2].left=c+"px";a[3].width=b+"px";a[3].left=c+"px";a[4].left=c+b-17+"px";this.w=b;this.max>this.maxHeight&&(this.w=b-20);this.isShow&&this.rSizeContent()};UIL.Bool=function(a){UIL.Proto.call(this,a);this.value=a.value||!1;this.buttonColor=UIL.BUTTON;this.inh=a.inh||this.h;a=~~(0.5*this.h)-0.5*(this.inh-2);this.c[2]=UIL.DOM(null,"div",UIL.BASIC+"background:"+UIL.BOOLBG+"; height:"+(this.inh-2)+"px; width:36px; top:"+a+"px; border-radius:20px; pointer-events:auto; cursor:pointer; transition:0.1s ease-out;");this.c[3]=UIL.DOM(null,"div",UIL.BASIC+"opasity:0, background:"+UIL.BOOLBG+"; height:"+(this.inh-6)+"px; width:"+(this.inh-6)+"px; top:"+(a+2)+"px; border-radius:20px; "); 98 | this.c[4]=UIL.DOM(null,"div",UIL.BASIC+"border:1px solid "+UIL.Border+"; height:"+(this.inh-4)+"px; width:16px; top:"+(a+1)+"px; border-radius:20px; background:"+this.buttonColor+"; transition:margin 0.1s ease-out;");this.value&&(this.c[4].style.marginLeft="18px",this.c[2].style.background=this.fontColor,this.c[2].style.borderColor=this.fontColor);this.c[2].events=["click"];this.init()};UIL.Bool.prototype=Object.create(UIL.Proto.prototype);UIL.Bool.prototype.constructor=UIL.Bool; 99 | UIL.Bool.prototype.handleEvent=function(a){a.preventDefault();switch(a.type){case "click":this.click(a)}};UIL.Bool.prototype.click=function(a){this.value=this.value?!1:!0;this.update();this.send()};UIL.Bool.prototype.rSize=function(){UIL.Proto.prototype.rSize.call(this);var a=this.s;a[2].left=this.sa+"px";a[3].left=this.sa+1+"px";a[4].left=this.sa+1+"px"}; 100 | UIL.Bool.prototype.update=function(){var a=this.s;this.value?(a[4].marginLeft="18px",a[2].background=this.fontColor,a[2].borderColor=this.fontColor,a[4].borderColor=this.fontColor):(a[4].marginLeft="0px",a[2].background=UIL.BOOLBG,a[2].borderColor=UIL.BOOLBG,a[4].borderColor=UIL.Border)};UIL.Button=function(a){UIL.Proto.call(this,a);this.value=a.value||[this.txt];this.buttonColor=a.bColor||UIL.BUTTON;this.isLoadButton=a.loader||!1;if(this.isDragButton=a.drag||!1)this.isLoadButton=!0;this.r=a.r||3;this.lng=this.value.length;for(a=0;aMath.PI?this.oldr:this.r,6a&&(this.r=this.twoPi)),a=1/this.twoPi*this.range*this.r+this.min-this.old,a>=this.step||a<=this.step)&&(a=~~(a/this.step),this.value=this.numValue(this.old+a*this.step),this.update(!0),this.old= 115 | this.value,this.oldr=this.r)};UIL.Circular.prototype.makePath=function(){var a=this.radius,b=this.percent*this.twoPi-0.001,c=a+a*Math.sin(b),d=a-a*Math.cos(b);return"M "+a+","+a+" L "+a+",0 A "+a+","+a+" 0 "+(b>Math.PI?1:0)+" 1 "+c+","+d+" Z"};UIL.Circular.prototype.update=function(a){this.c[2].textContent=this.value;this.percent=(this.value-this.min)/this.range;UIL.setSvg(this.c[4],"d",this.makePath());a&&this.send()};UIL.Knob=function(a){UIL.Proto.call(this,a);this.autoWidth=!1;this.buttonColor=UIL.BUTTON;this.setTypeNumber(a);this.mPI=0.8*Math.PI;this.toDeg=180/Math.PI;this.cirRange=2*this.mPI;this.radius=a.radius||15;this.width=2*this.radius+20;void 0!==a.width&&(this.width=a.width,this.radius=0.5*~~(this.width-20));void 0!==a.size&&(this.width=a.size,this.radius=0.5*~~(this.width-20));this.w=this.height=2*this.radius;this.h=a.height||this.height+40;this.top=0;this.c[0].style.width=this.width+"px";void 0!== 116 | this.c[1]&&(this.c[1].style.width=this.width+"px",this.c[1].style.textAlign="center",this.top=20);this.percent=0;this.c[2]=UIL.DOM(null,"div",UIL.NUM+"text-align:center; top:"+(this.height+24)+"px; width:"+this.width+"px; color:"+this.fontColor);this.c[3]=UIL.DOM(null,"circle",UIL.BASIC+"left:10px; top:"+this.top+"px; width:"+this.w+"px; height:"+this.height+"px; pointer-events:auto; cursor:pointer;",{cx:this.radius,cy:this.radius,r:this.radius-4,fill:"rgba(0,0,0,0.3)"});this.c[4]=UIL.DOM(null,"circle", 117 | UIL.BASIC+"left:10px; top:"+this.top+"px; width:"+this.w+"px; height:"+this.height+"px;",{cx:this.radius,cy:0.5*this.radius,r:3,fill:this.fontColor});this.c[5]=UIL.DOM(null,"path",UIL.BASIC+"left:10px; top:"+this.top+"px; width:"+this.w+"px; height:"+this.height+"px;",{d:this.makeGrad(),"stroke-width":1,stroke:UIL.SVGC});UIL.DOM(null,"circle",null,{cx:this.radius,cy:this.radius,r:0.7*this.radius,fill:this.buttonColor,"stroke-width":1,stroke:UIL.SVGC},this.c[3]);this.c[3].events=["mouseover","mousedown", 118 | "mouseout"];this.r=0;this.init();this.update()};UIL.Knob.prototype=Object.create(UIL.Circular.prototype);UIL.Knob.prototype.constructor=UIL.Knob; 119 | UIL.Knob.prototype.move=function(a){this.isDown&&(this.r=-Math.atan2(this.radius-(a.clientX-this.rect.left),this.radius-(a.clientY-this.rect.top)),null!==this.oldr&&(this.r=Math.abs(this.r-this.oldr)>Math.PI?this.oldr:this.r),this.r=this.r>this.mPI?this.mPI:this.r,this.r=this.r<-this.mPI?-this.mPI:this.r,a=1/this.cirRange*this.range*(this.r+this.mPI)+this.min-this.old,a>=this.step||a<=this.step)&&(a=~~(a/this.step),this.value=this.numValue(this.old+a*this.step),this.update(!0),this.old=this.value, 120 | this.oldr=this.r)};UIL.Knob.prototype.makeGrad=function(){var a="",b,c,d,e,f,h,g=this.radius,l=Math.PI+this.mPI;b=Math.PI-this.mPI;5this.maxDistance&&(a=Math.atan2(b,a),b=Math.sin(a)*this.maxDistance,a=Math.cos(a)*this.maxDistance);this.x=b/this.maxDistance;this.y=a/this.maxDistance;this.update()}}; 132 | UIL.Joystick.prototype.update=function(a){void 0===a&&(a=!0);null!==this.interval&&(this.isDown||(this.x+=(0-this.x)/3,this.y+=(0-this.y)/3),this.x.toFixed(2)===this.oldx.toFixed(2)&&this.y.toFixed(2)===this.oldy.toFixed(2)&&(this.y=this.x=0));var b=this.radius-this.x*this.maxDistance,c=this.radius-this.y*this.maxDistance,d=b+5*(1-this.x)+5,e=c+5*(1-this.y)+10;this.value[0]=1*-(this.x*this.multiplicator).toFixed(this.precision);this.value[1]=1*(this.y*this.multiplicator).toFixed(this.precision);this.c[5].textContent= 133 | "x"+this.value[0]+" y"+this.value[1];UIL.setSvg(this.c[3],"cx",d);UIL.setSvg(this.c[3],"cy",e);UIL.setSvg(this.c[4],"cx",b);UIL.setSvg(this.c[4],"cy",c);this.oldx=this.x;this.oldy=this.y;a&&this.send();null!==this.interval&&0===this.x&&0===this.y&&(clearInterval(this.interval),this.interval=null)};UIL.Fps=function(a){UIL.Proto.call(this,a);this.round=Math.round;this.autoHeight=!0;this.baseH=this.h;this.hplus=50;this.res=a.res||40;this.l=1;this.pa1=[];this.pa2=[];this.pa3=[];for(var b=this.res+1;b--;)this.pa1.push(50),this.pa2.push(50),this.pa3.push(50);b=Math.floor(0.5*this.h)-6;this.c[1].textContent="FPS";this.c[0].style.cursor="pointer";this.c[0].style.pointerEvents="auto";this.c[2]=UIL.DOM(null,"path",UIL.BASIC+("display:none; left:10px; top:"+this.h+"px; height:"+(this.hplus-8)+"px; background: rgba(0, 0, 0, 0.2);border:1px solid rgba(255, 255, 255, 0.2); "), 134 | {fill:"rgba(200,200,200,0.3)","stroke-width":1,stroke:this.fontColor,"vector-effect":"non-scaling-stroke"});this.c[2].setAttribute("viewBox","0 0 "+this.res+" 42");this.c[2].setAttribute("height","100%");this.c[2].setAttribute("width","100%");this.c[2].setAttribute("preserveAspectRatio","none");UIL.DOM(null,"path",null,{fill:"rgba(255,255,0,0.3)","stroke-width":1,stroke:"#FF0","vector-effect":"non-scaling-stroke"},this.c[2]);UIL.DOM(null,"path",null,{fill:"rgba(0,255,255,0.3)","stroke-width":1,stroke:"#0FF", 135 | "vector-effect":"non-scaling-stroke"},this.c[2]);this.c[3]=UIL.DOM(null,"div",UIL.BASIC+"width:100%; bottom:0px; height:1px; background: rgba(255, 255, 255, 0.2);");this.c[4]=UIL.DOM(null,"path",UIL.BASIC+"position:absolute; width:10px; height:10px; left:4px; top:"+b+"px;",{d:"M 3 8 L 8 5 3 2 3 8 Z",fill:this.fontColor,stroke:"none"});this.isShow=a.show||!1;this.c[1].style.marginLeft="10px";this.now=self.performance&&self.performance.now?self.performance.now.bind(performance):Date.now;this.prevTime= 136 | this.startTime=this.now();this.frames=0;this.isMem=!1;this.mm=this.mem=this.fps=this.ms=0;self.performance&&self.performance.memory&&(this.isMem=!0);this.c[0].events=["click","mousedown","mouseover","mouseout"];this.init()};UIL.Fps.prototype=Object.create(UIL.Proto.prototype);UIL.Fps.prototype.constructor=UIL.Fps;UIL.Fps.prototype.handleEvent=function(a){a.preventDefault();switch(a.type){case "click":this.click(a);break;case "mouseover":this.mode(1);break;case "mousedown":this.mode(2);break;case "mouseout":this.mode(0)}}; 137 | UIL.Fps.prototype.click=function(a){this.isShow?this.hide():this.show()};UIL.Fps.prototype.mode=function(a){var b=this.s;switch(a){case 0:b[1].color=this.fontColor;break;case 1:b[1].color="#FFF";break;case 2:b[1].color=this.fontColor}};UIL.Fps.prototype.makePath=function(a){var b;b="M -1 50";for(var c=0;cthis.prevTime+1E3&&(this.fps=this.round(1E3*this.frames/(a-this.prevTime)),this.prevTime=a,this.frames=0,this.isMem)){var b=performance.memory.usedJSHeapSize,c=performance.memory.jsHeapSizeLimit;this.mem=this.round(9.54E-7*b);this.mm=b/c}this.drawGraph();this.c[1].innerHTML="FPS "+this.fps+' . MS '+(this.ms|0)+' . MB '+this.mem+"";return a}; 143 | UIL.Fps.prototype.listening=function(){this.startTime=this.end()}; 144 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Finding Love Shaders 2 | This repository demonstrates shaders from 3 prominent elements of the [Finding Love](https://findinglove.activetheory.net) experience. 3 | 4 | The demo code uses latest ES6 features without transpilation, so Chrome is recommended. 5 | 6 | To view, [create a local environment if necessary](https://threejs.org/docs/#Manual/Getting_Started/How_to_run_things_locally), and point your browser to: 7 | 8 | `http://localhost/#Gem` 9 | ![Preview](http://i.imgur.com/yd9QhyV.png) 10 | 11 | `http://localhost/#Sky` 12 | ![Preview](http://i.imgur.com/zcQQacc.png) 13 | 14 | `http://localhost/#Terrain` 15 | ![Preview](http://i.imgur.com/5Wl3SCf.png) 16 | 17 | You'll be able to adjust shader uniforms directly in browser and the shaders themselves are in the `shaders/` folder. 18 | -------------------------------------------------------------------------------- /shaders/Gem.fs: -------------------------------------------------------------------------------- 1 | uniform vec3 lightColor; 2 | uniform float strength; 3 | uniform float LTPower; 4 | uniform float LTScale; 5 | uniform float LTDistortion; 6 | uniform float LTAmbient; 7 | uniform float shininess; 8 | uniform float radius; 9 | uniform float time; 10 | uniform float darkness; 11 | uniform float disableFX; 12 | uniform float translucencyMix; 13 | uniform vec2 resolution; 14 | uniform vec2 offsetUV; 15 | 16 | varying vec3 vPos; 17 | varying vec3 vEyeDir; 18 | varying vec3 vLightDir; 19 | varying vec3 vNormal; 20 | varying vec2 vUv; 21 | 22 | float kC = 0.5; 23 | float kL = 0.05; 24 | float kQ = 0.0001; 25 | 26 | float range(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 27 | float oldRange = oldMax - oldMin; 28 | float newRange = newMax - newMin; 29 | return (((oldValue - oldMin) * newRange) / oldRange) + newMin; 30 | } 31 | 32 | float crange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 33 | return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), newMin, newMax); 34 | } 35 | 36 | vec3 rgb2hsv(vec3 c) { 37 | vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); 38 | vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); 39 | vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); 40 | 41 | float d = q.x - min(q.w, q.y); 42 | float e = 1.0e-10; 43 | return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); 44 | } 45 | 46 | vec3 hsv2rgb(vec3 c) { 47 | vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 48 | vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); 49 | return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); 50 | } 51 | 52 | vec3 mod289(vec3 x) { 53 | return x - floor(x * (1.0 / 289.0)) * 289.0; 54 | } 55 | 56 | vec4 mod289(vec4 x) { 57 | return x - floor(x * (1.0 / 289.0)) * 289.0; 58 | } 59 | 60 | vec4 permute(vec4 x) { 61 | return mod289(((x*34.0)+1.0)*x); 62 | } 63 | 64 | vec4 taylorInvSqrt(vec4 r) { 65 | return 1.79284291400159 - 0.85373472095314 * r; 66 | } 67 | 68 | float snoise(vec3 v) { 69 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 70 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 71 | 72 | vec3 i = floor(v + dot(v, C.yyy) ); 73 | vec3 x0 = v - i + dot(i, C.xxx) ; 74 | 75 | vec3 g = step(x0.yzx, x0.xyz); 76 | vec3 l = 1.0 - g; 77 | vec3 i1 = min( g.xyz, l.zxy ); 78 | vec3 i2 = max( g.xyz, l.zxy ); 79 | 80 | vec3 x1 = x0 - i1 + C.xxx; 81 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 82 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 83 | 84 | i = mod289(i); 85 | vec4 p = permute( permute( permute( 86 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 87 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 88 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 89 | 90 | float n_ = 0.142857142857; // 1.0/7.0 91 | vec3 ns = n_ * D.wyz - D.xzx; 92 | 93 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 94 | 95 | vec4 x_ = floor(j * ns.z); 96 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 97 | 98 | vec4 x = x_ *ns.x + ns.yyyy; 99 | vec4 y = y_ *ns.x + ns.yyyy; 100 | vec4 h = 1.0 - abs(x) - abs(y); 101 | 102 | vec4 b0 = vec4( x.xy, y.xy ); 103 | vec4 b1 = vec4( x.zw, y.zw ); 104 | 105 | vec4 s0 = floor(b0)*2.0 + 1.0; 106 | vec4 s1 = floor(b1)*2.0 + 1.0; 107 | vec4 sh = -step(h, vec4(0.0)); 108 | 109 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 110 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 111 | 112 | vec3 p0 = vec3(a0.xy,h.x); 113 | vec3 p1 = vec3(a0.zw,h.y); 114 | vec3 p2 = vec3(a1.xy,h.z); 115 | vec3 p3 = vec3(a1.zw,h.w); 116 | 117 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 118 | p0 *= norm.x; 119 | p1 *= norm.y; 120 | p2 *= norm.z; 121 | p3 *= norm.w; 122 | 123 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 124 | m = m * m; 125 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); 126 | } 127 | 128 | vec3 desaturate(vec3 color, float amount) { 129 | vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color)); 130 | return vec3(mix(color, gray, amount)); 131 | } 132 | 133 | vec3 getColor() { 134 | float noise = snoise((vPos * 0.8) + time); 135 | vec3 color = rgb2hsv(lightColor); 136 | color.x += 0.05 * noise; 137 | color.z -= darkness; 138 | color = hsv2rgb(color); 139 | return color; 140 | } 141 | 142 | vec2 getScreenUV() { 143 | return gl_FragCoord.xy / resolution; 144 | } 145 | 146 | float getLum(vec3 color) { 147 | return (color.r + color.g + color.b) / 3.0; 148 | } 149 | 150 | void main() { 151 | vec3 normal = vNormal; 152 | 153 | vec3 diffuse = vec3(1.0); 154 | 155 | vec3 N = normalize(normal); 156 | vec3 L = normalize(vLightDir); 157 | vec3 V = normalize(vEyeDir); 158 | 159 | vec3 lightPosition = vec3(0.0); 160 | 161 | float d = length(lightPosition - vPos); 162 | float lightAttenuation = (1.0 / (kC + kL*d + kQ*d*d)) * strength; 163 | 164 | float thickness = range(length(vPos), 0.0, radius, 1.0, 0.5); 165 | vec3 ltLight = normalize(L + (N * LTDistortion)); 166 | float ltDot = clamp(dot(V, -ltLight), 0.0, 1.0) * LTScale; 167 | float LT = lightAttenuation * (ltDot + LTAmbient) * thickness; 168 | 169 | vec3 finalColor = diffuse * getColor() * LT; 170 | vec3 outputColor = finalColor; 171 | 172 | gl_FragColor = vec4(outputColor, 1.0); 173 | } 174 | -------------------------------------------------------------------------------- /shaders/Gem.vs: -------------------------------------------------------------------------------- 1 | varying vec3 vPos; 2 | varying vec3 vEyeDir; 3 | varying vec3 vLightDir; 4 | varying vec3 vNormal; 5 | varying vec2 vUv; 6 | 7 | void main() { 8 | vec3 lightPosition = vec3(0.0); 9 | 10 | vUv = uv; 11 | vPos = position; 12 | vEyeDir = normalize(cameraPosition - position.xyz); 13 | vLightDir = normalize(lightPosition - position.xyz); 14 | vNormal = normalMatrix * normal; 15 | 16 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 17 | } 18 | -------------------------------------------------------------------------------- /shaders/Sky.fs: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform float sat; 3 | uniform vec3 color; 4 | 5 | varying vec3 vPos; 6 | 7 | float range(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 8 | float oldRange = oldMax - oldMin; 9 | float newRange = newMax - newMin; 10 | return (((oldValue - oldMin) * newRange) / oldRange) + newMin; 11 | } 12 | 13 | float crange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 14 | return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), newMin, newMax); 15 | } 16 | 17 | // Description : Array and textureless GLSL 2D/3D/4D simplex 18 | // noise functions. 19 | // Author : Ian McEwan, Ashima Arts. 20 | // Maintainer : ijm 21 | // Lastmod : 20110822 (ijm) 22 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 23 | // Distributed under the MIT License. See LICENSE file. 24 | // https://github.com/ashima/webgl-noise 25 | // 26 | 27 | vec3 mod289(vec3 x) { 28 | return x - floor(x * (1.0 / 289.0)) * 289.0; 29 | } 30 | 31 | vec4 mod289(vec4 x) { 32 | return x - floor(x * (1.0 / 289.0)) * 289.0; 33 | } 34 | 35 | vec4 permute(vec4 x) { 36 | return mod289(((x*34.0)+1.0)*x); 37 | } 38 | 39 | vec4 taylorInvSqrt(vec4 r) { 40 | return 1.79284291400159 - 0.85373472095314 * r; 41 | } 42 | 43 | float snoise(vec3 v) { 44 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 45 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 46 | 47 | vec3 i = floor(v + dot(v, C.yyy) ); 48 | vec3 x0 = v - i + dot(i, C.xxx) ; 49 | 50 | vec3 g = step(x0.yzx, x0.xyz); 51 | vec3 l = 1.0 - g; 52 | vec3 i1 = min( g.xyz, l.zxy ); 53 | vec3 i2 = max( g.xyz, l.zxy ); 54 | 55 | vec3 x1 = x0 - i1 + C.xxx; 56 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 57 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 58 | 59 | i = mod289(i); 60 | vec4 p = permute( permute( permute( 61 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 62 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 63 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 64 | 65 | float n_ = 0.142857142857; // 1.0/7.0 66 | vec3 ns = n_ * D.wyz - D.xzx; 67 | 68 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 69 | 70 | vec4 x_ = floor(j * ns.z); 71 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 72 | 73 | vec4 x = x_ *ns.x + ns.yyyy; 74 | vec4 y = y_ *ns.x + ns.yyyy; 75 | vec4 h = 1.0 - abs(x) - abs(y); 76 | 77 | vec4 b0 = vec4( x.xy, y.xy ); 78 | vec4 b1 = vec4( x.zw, y.zw ); 79 | 80 | vec4 s0 = floor(b0)*2.0 + 1.0; 81 | vec4 s1 = floor(b1)*2.0 + 1.0; 82 | vec4 sh = -step(h, vec4(0.0)); 83 | 84 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 85 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 86 | 87 | vec3 p0 = vec3(a0.xy,h.x); 88 | vec3 p1 = vec3(a0.zw,h.y); 89 | vec3 p2 = vec3(a1.xy,h.z); 90 | vec3 p3 = vec3(a1.zw,h.w); 91 | 92 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 93 | p0 *= norm.x; 94 | p1 *= norm.y; 95 | p2 *= norm.z; 96 | p3 *= norm.w; 97 | 98 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 99 | m = m * m; 100 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); 101 | } 102 | 103 | //float surface(vec3 coord) { 104 | // float n = 0.0; 105 | // n += 1.0 * abs(snoise(coord)); 106 | // n += 0.5 * abs(snoise(coord * 2.0)); 107 | // n += 0.25 * abs(snoise(coord * 4.0)); 108 | // n += 0.125 * abs(snoise(coord * 8.0)); 109 | // float rn = 1.0 - n; 110 | // return rn * rn; 111 | //} 112 | 113 | vec3 rgb2hsv(vec3 c) { 114 | vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); 115 | vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); 116 | vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); 117 | 118 | float d = q.x - min(q.w, q.y); 119 | float e = 1.0e-10; 120 | return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); 121 | } 122 | 123 | vec3 hsv2rgb(vec3 c) { 124 | vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 125 | vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); 126 | return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); 127 | } 128 | 129 | vec3 desaturate(vec3 color, float amount) { 130 | vec3 gray = vec3(dot(vec3(0.2126,0.7152,0.0722), color)); 131 | return vec3(mix(color, gray, amount)); 132 | } 133 | 134 | vec3 offsetColor(float noise) { 135 | vec3 c = rgb2hsv(color); 136 | c.x += 0.25; 137 | c = hsv2rgb(c); 138 | return c; 139 | } 140 | 141 | void main() { 142 | float fNoise = snoise((vPos * 0.01) + time * 10.0); 143 | float noise = range(fNoise, -1.0, 1.0, 0.0, 1.0); 144 | 145 | vec3 color0 = color; 146 | vec3 color1 = offsetColor(fNoise); 147 | 148 | vec3 finalColor = mix(color0, color1, noise); 149 | 150 | finalColor *= clamp(range(abs(vPos.y), 0.0, 25.0, 1.2, 1.0), 1.0, 15.0); 151 | 152 | finalColor = rgb2hsv(finalColor); 153 | finalColor.z -= range(sat, 0.0, 1.0, 0.0, 0.7); 154 | finalColor = hsv2rgb(finalColor); 155 | 156 | gl_FragColor = vec4(finalColor, 1.0); 157 | } 158 | -------------------------------------------------------------------------------- /shaders/Sky.vs: -------------------------------------------------------------------------------- 1 | varying vec3 vPos; 2 | 3 | void main() { 4 | vPos = position; 5 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 6 | } 7 | -------------------------------------------------------------------------------- /shaders/Terrain.fs: -------------------------------------------------------------------------------- 1 | uniform vec3 baseColor; 2 | uniform float transition; 3 | uniform float transHeight; 4 | uniform float transDirection; 5 | uniform vec3 multiplyColor; 6 | uniform vec3 lightPos; 7 | uniform vec3 lightColor; 8 | uniform mat4 modelViewMatrix; 9 | 10 | varying vec3 vViewPosition; 11 | varying vec3 vWorldPos; 12 | varying vec3 vPos; 13 | varying vec2 vUv; 14 | varying float vAlpha; 15 | varying float vSat; 16 | 17 | vec3 rgb2hsv(vec3 c) { 18 | vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); 19 | vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); 20 | vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); 21 | 22 | float d = q.x - min(q.w, q.y); 23 | float e = 1.0e-10; 24 | return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); 25 | } 26 | 27 | vec3 hsv2rgb(vec3 c) { 28 | vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 29 | vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); 30 | return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); 31 | } 32 | 33 | float range(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 34 | float oldRange = oldMax - oldMin; 35 | float newRange = newMax - newMin; 36 | return (((oldValue - oldMin) * newRange) / oldRange) + newMin; 37 | } 38 | 39 | float crange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 40 | return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), newMin, newMax); 41 | } 42 | 43 | vec3 worldLight(vec3 pos, vec3 vpos) { 44 | vec4 mvPos = modelViewMatrix * vec4(vpos, 1.0); 45 | vec4 worldPosition = viewMatrix * vec4(pos, 1.0); 46 | return worldPosition.xyz - mvPos.xyz; 47 | } 48 | 49 | float transitionMask(vec2 vuv) { 50 | float dist = length(vec2(0.5) - vuv); 51 | float r = range(dist, 0.0, 0.5, 0.0, 1.0); 52 | float a = step(1.0 - r, transition); 53 | float b = step(r, transition); 54 | return mix(a, b, transDirection); 55 | } 56 | 57 | float heightMask(vec2 vuv) { 58 | float dist = length(vec2(0.5) - vuv); 59 | float r = range(dist, 0.0, 0.5, 0.0, 1.0); 60 | float a = 1.0 - smoothstep(transHeight - 0.5, transHeight + 0.5, 1.0 - r); 61 | float b = 1.0 - smoothstep(transHeight - 0.5, transHeight + 0.5, r); 62 | 63 | float height = mix(a, b, transDirection); 64 | 65 | return height; 66 | } 67 | 68 | vec3 getDNormal(vec3 viewPos) { 69 | vec3 dfx = vec3(0.0); 70 | vec3 dfy = vec3(0.0); 71 | 72 | dfx.x = dFdx(viewPos.x); 73 | dfx.y = dFdx(viewPos.y); 74 | dfx.z = dFdx(viewPos.z); 75 | 76 | dfy.x = dFdy(viewPos.x); 77 | dfy.y = dFdy(viewPos.y); 78 | dfy.z = dFdy(viewPos.z); 79 | 80 | return cross(dfx, dfy); 81 | } 82 | 83 | vec3 calculateLight(vec3 worldPos, vec3 n) { 84 | vec3 lPos = worldLight(lightPos, vPos); 85 | float volume = max(dot(normalize(lPos), n), 0.0); 86 | 87 | vec3 color = mix(baseColor, lightColor, volume); 88 | color *= range(volume, 0.0, 1.0, 0.8, 1.0); 89 | 90 | return color; 91 | } 92 | 93 | float getFogAmount() { 94 | vec2 pos = vPos.xz; 95 | return pow(smoothstep(25.0, 35.0, length(pos)), 2.0); 96 | } 97 | 98 | void main() { 99 | vec3 normal = normalize(getDNormal(vViewPosition)); 100 | 101 | vec3 terrain = calculateLight(vWorldPos, normal) * multiplyColor; 102 | terrain = rgb2hsv(terrain); 103 | terrain.y += vSat; 104 | terrain = hsv2rgb(terrain); 105 | gl_FragColor = vec4(terrain, 1.0); 106 | 107 | gl_FragColor = mix(gl_FragColor, vec4(0.0), getFogAmount()); 108 | gl_FragColor.a *= transitionMask(vUv); 109 | 110 | if (gl_FragColor.a < 0.01) discard; 111 | } 112 | -------------------------------------------------------------------------------- /shaders/Terrain.vs: -------------------------------------------------------------------------------- 1 | uniform float time; 2 | uniform float transHeight; 3 | uniform float transition; 4 | uniform float transDirection; 5 | uniform sampler2D tTransition; 6 | 7 | varying vec3 vWorldPos; 8 | varying vec3 vViewPosition; 9 | varying vec3 vPos; 10 | varying vec2 vUv; 11 | varying float vAlpha; 12 | varying float vSat; 13 | 14 | float range(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 15 | float oldRange = oldMax - oldMin; 16 | float newRange = newMax - newMin; 17 | return (((oldValue - oldMin) * newRange) / oldRange) + newMin; 18 | } 19 | 20 | float crange(float oldValue, float oldMin, float oldMax, float newMin, float newMax) { 21 | return clamp(range(oldValue, oldMin, oldMax, newMin, newMax), newMin, newMax); 22 | } 23 | 24 | // Description : Array and textureless GLSL 2D/3D/4D simplex 25 | // noise functions. 26 | // Author : Ian McEwan, Ashima Arts. 27 | // Maintainer : ijm 28 | // Lastmod : 20110822 (ijm) 29 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 30 | // Distributed under the MIT License. See LICENSE file. 31 | // https://github.com/ashima/webgl-noise 32 | // 33 | 34 | vec3 mod289(vec3 x) { 35 | return x - floor(x * (1.0 / 289.0)) * 289.0; 36 | } 37 | 38 | vec4 mod289(vec4 x) { 39 | return x - floor(x * (1.0 / 289.0)) * 289.0; 40 | } 41 | 42 | vec4 permute(vec4 x) { 43 | return mod289(((x*34.0)+1.0)*x); 44 | } 45 | 46 | vec4 taylorInvSqrt(vec4 r) { 47 | return 1.79284291400159 - 0.85373472095314 * r; 48 | } 49 | 50 | float snoise(vec3 v) { 51 | const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 52 | const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 53 | 54 | vec3 i = floor(v + dot(v, C.yyy) ); 55 | vec3 x0 = v - i + dot(i, C.xxx) ; 56 | 57 | vec3 g = step(x0.yzx, x0.xyz); 58 | vec3 l = 1.0 - g; 59 | vec3 i1 = min( g.xyz, l.zxy ); 60 | vec3 i2 = max( g.xyz, l.zxy ); 61 | 62 | vec3 x1 = x0 - i1 + C.xxx; 63 | vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 64 | vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 65 | 66 | i = mod289(i); 67 | vec4 p = permute( permute( permute( 68 | i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 69 | + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 70 | + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 71 | 72 | float n_ = 0.142857142857; // 1.0/7.0 73 | vec3 ns = n_ * D.wyz - D.xzx; 74 | 75 | vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 76 | 77 | vec4 x_ = floor(j * ns.z); 78 | vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 79 | 80 | vec4 x = x_ *ns.x + ns.yyyy; 81 | vec4 y = y_ *ns.x + ns.yyyy; 82 | vec4 h = 1.0 - abs(x) - abs(y); 83 | 84 | vec4 b0 = vec4( x.xy, y.xy ); 85 | vec4 b1 = vec4( x.zw, y.zw ); 86 | 87 | vec4 s0 = floor(b0)*2.0 + 1.0; 88 | vec4 s1 = floor(b1)*2.0 + 1.0; 89 | vec4 sh = -step(h, vec4(0.0)); 90 | 91 | vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 92 | vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 93 | 94 | vec3 p0 = vec3(a0.xy,h.x); 95 | vec3 p1 = vec3(a0.zw,h.y); 96 | vec3 p2 = vec3(a1.xy,h.z); 97 | vec3 p3 = vec3(a1.zw,h.w); 98 | 99 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 100 | p0 *= norm.x; 101 | p1 *= norm.y; 102 | p2 *= norm.z; 103 | p3 *= norm.w; 104 | 105 | vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 106 | m = m * m; 107 | return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); 108 | } 109 | 110 | float aastep(float threshold, float value, float buf) { 111 | return smoothstep(threshold - buf, threshold + buf, value); 112 | } 113 | 114 | float transitionMask(vec2 vuv) { 115 | float dist = length(vec2(0.5) - vuv); 116 | float r = range(dist, 0.0, 0.5, 0.0, 1.0); 117 | float a = step(1.0 - r, transition); 118 | float b = step(r, transition); 119 | return mix(a, b, transDirection); 120 | } 121 | 122 | float cubicOut(float t) { 123 | float f = t - 1.0; 124 | return f * f * f + 1.0; 125 | } 126 | 127 | float quarticInOut(float t) { 128 | return t < 0.5 129 | ? +8.0 * pow(t, 4.0) 130 | : -8.0 * pow(t - 1.0, 4.0) + 1.0; 131 | } 132 | 133 | float heightMask(vec2 vuv) { 134 | float dist = length(vec2(0.5) - vuv); 135 | float r = range(dist, 0.0, 0.5, 0.0, 1.0); 136 | float a = 1.0 - smoothstep(transHeight - 0.5, transHeight + 0.5, 1.0 - r); 137 | float b = 1.0 - smoothstep(transHeight - 0.5, transHeight + 0.5, r); 138 | 139 | float height = mix(a, b, transDirection); 140 | 141 | return height; 142 | } 143 | 144 | void main() { 145 | float noise = range(snoise((position * 0.054) + time), -1.0, 1.0, 0.0, 1.0); 146 | noise = 1.0 - aastep(0.3, noise, 0.4); 147 | 148 | vAlpha = transitionMask(uv); 149 | 150 | float posLen = length(position); 151 | float height = range(posLen, 5.0, 30.0, 0.2, 20.0); 152 | 153 | float raise = height * noise; 154 | raise *= crange(posLen, 5.0, 10.0, 0.2, 1.0); 155 | 156 | vec3 pos = position; 157 | pos.y += raise * heightMask(uv); 158 | 159 | vSat = crange(pos.y, 0.0, 6.0, 0.0, 0.1); 160 | 161 | vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0); 162 | vViewPosition = -mvPosition.xyz; 163 | vWorldPos = (vec4(pos, 1.0) * modelMatrix).xyz; 164 | vPos = pos; 165 | vUv = uv; 166 | gl_Position = projectionMatrix * mvPosition; 167 | } 168 | --------------------------------------------------------------------------------