最近做項目很忙,好久沒寫博客了,前幾天看到騰訊回憶時光的一個頁面,使用了點雲拼湊出了照片輪播十分有趣,於是我想用threejs實現這個效果。
首先這件事情分爲兩步:1.根據圖片數據創建對應大小、顏色的點雲。2.給點雲加上着色器,給渲染管線傳遞點雲變換需要的數據(位置數據,顏色數據)。
今天我們先來實現加載圖片並且通過圖片數據加載點雲:
首先繪製一個200*200的畫布,然後將圖片繪製到畫布上,接下來將圖片數據存放到進行存儲,等待後面使用。
canvas = document.createElement('canvas'); content = canvas.getContext('2d'); canvas.width = 200; canvas.height = 200; document.body.appendChild( canvas ); // container.appendChild( canvas ); img = new Image(); img.src = "bg1.jpg"; canvas.style.position = 'absolute'; img.onload = function () { content.drawImage(img, 10, 10, canvas.width, canvas.height); imgDate = content.getImageData(0,0,canvas.width, canvas.height); createPotCloud(); //創建點雲 };當圖片加載完成之後調用創建點雲的方法~不然會出現錯誤。首先根據畫布長寬像素,創建相應數量的點對象,positions和colors存放每個點的位置座標和顏色信息(這裏的顏色只有rgb沒有a),最後把這些信息加入geometry對象的attribute裏面,這裏特別要注意的有兩點:
1.imgData裏面的數據與圖片是上下顛倒的需要用canvas.height-i纔可以得到正確的圖像。
2.圖片數據在canvas裏面最大值是255而在threejs裏面是1所以需要給每個顏色值除以255.0纔可以得到正確的顏色,不然全都是白色的。
這樣就完成了點雲的創建,等有時間在做點雲照片的交互~。
function createPotCloud() { //創建點雲 console.log(imgDate); var particles = canvas.width * canvas.height; var geometry = new THREE.BufferGeometry(); var positions = new Float32Array( particles * 3 ); var colors = new Float32Array( particles * 3 ); for ( var i = 0; i < positions.length; i ++ ) { // positions positions[ 3*i ] = parseInt(i%canvas.width); positions[ 3*i + 1 ] = 200+ parseInt((canvas.height-i)/canvas.width) ; positions[ 3*i + 2 ] = 0; // colors colors[ 3*i ] = imgDate.data[ 4*i ]/255.0; colors[ 3*i + 1 ] = imgDate.data[ 4*i + 1]/255.0; colors[ 3*i + 2 ] = imgDate.data[ 4*i + 2]/255.0; } geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) ); // geometry.computeBoundingSphere(); console.log("geometry",geometry); var material = new THREE.PointsMaterial( { size: 1, vertexColors: THREE.VertexColors } ); var points = new THREE.Points( geometry, material ); scene.add( points ); }最後讓我們看看實現的效果吧:
最後附上github的地址:https://github.com/StringKun/ThreeJSPotCloud