UNPKG

displacement-map

Version:
83 lines (60 loc) 4.89 kB
/** * WorkerString magic - regex replaces this empty string with built worker code string * @TODO this is fragile and will need some love */ 'use strict'; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var displacementLineWorkerString = '"use strict";var buf8,roughness;function clamp(num){return Math.min(Math.max(num,0),255)}function variance(){return-128+Math.random()*255}function generateMidpoint(start,end){var length=end-start;var avg=(buf8[end]+buf8[start])/2;var displacement=.5*variance()*roughness*(length/buf8.length-1);buf8[start+length/2]=clamp(avg*1+displacement)}function generate(step){if(!step){step=1}var size=(buf8.length-1)*step;for(var i=0;i<buf8.length-1;i+=size){generateMidpoint(i,i+size)}if(size>2){generate(step*.5);return}done()}self.addEventListener("message",function(event){buf8=event.data.buf8;roughness=event.data.roughness||1;generate()});function done(){self.postMessage({buf8:buf8})}'; var displacementMapWorkerString = '"use strict";var map,height,width,roughness;function clamp(num){return Math.min(Math.max(num,0),255)}function to1d(x,y){return y*width+x}function wrapX(num){var min=0;var max=width-1;if(num>max){return num%max}if(num<min){return max-(min-num)%(max-min)}return num}function wrapY(num){var min=0;var max=height-1;if(num>max){return num%max}if(num<min){return max-(min-num)%(max-min)}return num}function get(x,y){return map[to1d(wrapX(x),wrapY(y))]}function set(x,y,value){map[to1d(wrapX(x),wrapY(y))]=value&255}function variance(){return-128+Math.random()*255}function getMidpointDisplacement(size){return clamp(variance()*roughness*(size/(width-1)))}function getAvg(){return Array.prototype.reduce.call(arguments,function(prev,num){return prev+num})/arguments.length}function getAvgEdge(x1,y1,x2,y2){var size=~~(x2-x1)/2;return getAvg(get(x1+size,y1),get(x1,y1+size),get(x2,y1+size),get(x1+size,y2))}function getAvgCorner(x1,y1,x2,y2){return getAvg(get(x1,y1),get(x2,y1),get(x1,y2),get(x2,y2))}function getAvgPoint(x,y,size){return getAvg(get(x,y-size),get(x+size,y),get(x-size,y),get(x,y+size))}function iterate(cb,step){var size=(width-1)*step;for(var x=0;x<width-1;x+=size){for(var y=0;y<height-1;y+=size){cb(x,y,size)}}}function performSquareStep(x,y,size){var mid=size/2;var avg=getAvgCorner(x,y,x+size,y+size);set(x+mid,y+mid,avg+getMidpointDisplacement(size))}function performDiamondStep(x,y,size){var mid=size/2;var setCell=function setCell(xx,yy){var avg=getAvgPoint(xx,yy,mid);set(xx,yy,avg+getMidpointDisplacement(size))};setCell(x+mid,y);setCell(x+mid,y+size);setCell(x,y+mid);setCell(x+size,y+mid)}function generate(step){if(!step){step=1}var size=(width-1)*step;iterate(performSquareStep,step);iterate(performDiamondStep,step);if(size>2){generate(step/2);return}done()}self.addEventListener("message",function(event){map=event.data.map;height=event.data.height;width=event.data.width;roughness=event.data.roughness||1;generate(1)});function done(){self.postMessage({map:map})}'; var mapBlob = new Blob([displacementMapWorkerString]); var mapURI = window.URL.createObjectURL(mapBlob); var lineBlob = new Blob([displacementLineWorkerString]); var lineURI = window.URL.createObjectURL(lineBlob); var Generator = (function () { function Generator(opts) { _classCallCheck(this, Generator); this.opts = opts || {}; } Generator.prototype.debug = function debug() { if (!this.opts.debug) { return; } console.log.apply(console, arguments); }; Generator.prototype.generate = function generate(opts) { var _this = this; return new Promise(function (resolve, reject) { var worker = new window.Worker(mapURI); worker.onmessage = function (event) { _this.debug('worker status:', event.data); worker.terminate(); resolve(event.data.map); }; worker.postMessage({ map: opts.map, width: opts.width, height: opts.height, roughness: opts.roughness }); }); }; Generator.prototype.generateLine = function generateLine(opts) { var _this2 = this; return new Promise(function (resolve, reject) { var worker = new window.Worker(lineURI); worker.onmessage = function (event) { _this2.debug('line worker status', event.data); worker.terminate(); resolve(event.data.buf8); }; worker.postMessage({ buf8: opts.buf8, roughness: opts.roughness }); }); }; return Generator; })(); exports['default'] = Generator; module.exports = exports['default'];