displacement-map
Version:
Mid-point displacement map
1 lines • 1.99 kB
JavaScript
;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})}