#javascript #алгоритм #canvas #webgl
Когда-то копаясь в проектах WebGL находил Depthy Исходник на github Возникло желание попрактиковаться с реализацией такого эффекта, после чего сразу покопался в исходниках, где нашел основной класс для этого. Конечно разбираться в непрокомментированном коде нет охоты (там же и PIXI, о котором я слышу впервые), поэтому решил сразу спросить здесь, может растолкуете сам принцип и этапы, но и я по ходу изучения может смогу добавить информации. В данный момент "под рукой" есть JS+Canvas, думаю для реализации этого будет достаточно Пока мысль лишь о том, чтобы каждый пиксель изображения смещать по заданному оффсету(в данном случае это позиция курсора относительно центра) полагаясь на значение того же пикселя на карте глубины. Может тогда возникнут разрывы пикселей и эффект Nearest фильтрации, о чем я не могу пока что лишь предположить, но и это по ходу дела решится?! Вот что получилось на данный момент чистым JS+Canvas this.render=function(ctx,offsetX,offsetY) { for (var i = 0, l = output.width * output.height * 4; i < l; i += 4) { if(i<0 || i>l)continue; var depthK = (255-depthData[i/4])/5000; var offset=i+Math.round((Math.floor(offsetY*depthK)*output.width+Math.floor(offsetX*depthK)))*4; output.data[i] = mapData[offset]; output.data[i + 1] = mapData[offset+1]; output.data[i + 2] = mapData[offset+2]; } ctx.putImageData(output,0,0); }; И это на WebGL. Быстрее и визуально приятнее. Весь код идентичен Hello World'овским, за исключением фрагментного шейдера, куда я передаю две текстуры, одна из которых накладывается на примитивы, а другая служит коэффициентом смещения для каждого пикселя по карте глубины precision mediump float; uniform sampler2D map; uniform sampler2D depth; uniform vec2 offset; varying vec2 uv; void main(void) { vec2 texCoord = (uv+offset*(1.0-texture2D(depth,uv).z)); gl_FragColor = vec4(texture2D(map,texCoord).xyz, 1.0); }
Ответы
Ответ 1
Вот вам галерея фильтров pixi. Поиграйтесь с displacement — это именно то, что вам нужно. А как захотите повторить — вот вам код для этого. Я сам с этой библиотекой не сильно знаком, но полагаю, если вы начнете со странички "basics" и дочитаете до фильтров, все станет понятно. Моя реализация: http://jsfiddle.net/ycj88zhs/2/ var image, depthMap, displacementMap; image = load( 'http://depthy.me/samples/hut-image.jpg', function () { depthMap = load( 'http://i.imgur.com/C4ZJY9m.jpg', function () { var renderer = PIXI.autoDetectRenderer( image.canvas.width, image.canvas.height); document.body.appendChild(renderer.view); var stage = new PIXI.Container(); stage.interactive = true; var container = new PIXI.Container(); stage.addChild(container); var displacementSprite = new PIXI.Sprite( PIXI.Texture.fromCanvas(depthMap.canvas)); displacementSprite.width = image.canvas.width; displacementSprite.height = image.canvas.height; stage.addChild(displacementSprite); var displacementFilter = new PIXI.filters. DisplacementFilter(displacementSprite); container.filters = [displacementFilter]; displacementFilter.scale.x = 10; displacementFilter.scale.y = 10; var bg = new PIXI.Sprite( PIXI.Texture.fromCanvas(image.canvas)); container.addChild(bg); stage.on('mousemove', onPointerMove) .on('touchmove', onPointerMove); renderer.render(stage); function onPointerMove(eventData) { var mouseOffsetX = eventData.data.global.x / image.canvas.width; var mouseOffsetY = eventData.data.global.y / image.canvas.height; displacementFilter.scale.x = mouseOffsetX * 20; displacementFilter.scale.y = mouseOffsetY * 20; renderer.render(stage); } }) }) function load(path, callback) { var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); var img = document.createElement('img'); img.crossOrigin = "Anonymous"; img.onload = function () { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); callback(canvas, ctx, img); }; img.src = path; return { context: ctx, image: img, canvas: canvas }; }
Комментариев нет:
Отправить комментарий