在上次按照自己的想法使用粒子系統對圖片進行處理之後,我最近又看到了官方案例中,使用粒子使視頻呈現出3D效果,既然是官方案例就需要仔細研究一下。
這是該案例的實現效果:可以看到屏幕中由粒子構成了一個人在整理桌面的東西,效果十分的酷炫,大家可以在官方案例中看到動態的效果。
官方案例地址:https://threejs.org/examples/#webgl_kinect
下面是我自己對於代碼的分析:程序首先創建了一個video視頻播放div,隨後設置好該視頻塊的播放參數,當視頻加載完成後將其當作材質,然後創建一個BufferGeometry對象,遍歷行列貼圖視頻的長寬,給BufferGeometry對象賦值(該對象具有視頻長像素個數*視頻寬像素個數個點,這也是一種利用粒子系統的方法),x,y的值分別按照長方形平鋪下去,z值不設置,將會在着色器裏對其進行計算,顯示出3D效果。
video = document.createElement( 'video' ); video.addEventListener( 'loadedmetadata', function ( event ) { //視頻紋理先加載完成 texture = new THREE.VideoTexture( video ); texture.minFilter = THREE.NearestFilter; //紋理縮放時採用最近點採樣 var width = 640, height = 480; var nearClipping = 850, farClipping = 4000; geometry = new THREE.BufferGeometry(); //創建buffergeometry var vertices = new Float32Array( width * height * 3 ); //創建數組填充到buffergeometry中 for ( var i = 0, j = 0, l = vertices.length; i < l; i += 3, j ++ ) { vertices[ i ] = j % width; //x方向的值 vertices[ i + 1 ] = Math.floor( j / width ); //y方向的值,z方向的值爲0 } geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );剩下一個重點就是片元着色器的處理,這裏的處理很有意思,首先這個視頻中人和物體的深度與顏色直接關聯,顏色越淺深度與大,根據顏色的RGB值加和求出該點的z值偏移量(也就是深度變量),再給它乘以一個值,經過處理讓相鄰的點之間的距離不那麼遠。還有就是這裏的uv展開沒有直接使用默認着色器給定的uv值,而是經過計算,將每一個點對應video長寬的值。
<script id="vs" type="x-shader/x-vertex"> uniform sampler2D map; uniform float width; uniform float height; uniform float nearClipping, farClipping; uniform float pointSize; uniform float zOffset; varying vec2 vUv; const float XtoZ = 1.11146; // tan( 1.0144686 / 2.0 ) * 2.0; const float YtoZ = 0.83359; // tan( 0.7898090 / 2.0 ) * 2.0; void main() { vUv = vec2( position.x / width, position.y / height ); vec4 color = texture2D( map, vUv ); float depth = ( color.r + color.g + color.b ) / 3.0; //顏色越暗值越大啊 // Projection code by @kcmic float z = ( 1.0 - depth ) * (farClipping - nearClipping) + nearClipping;//計算z值 vec4 pos = vec4( ( position.x / width - 0.5 ) * z * XtoZ, //讓畫面偏移不變形 ( position.y / height - 0.5 ) * z * YtoZ, - z + zOffset, 1.0); gl_PointSize = pointSize; gl_Position = projectionMatrix * modelViewMatrix * pos; } </script>如果想自己實現這個效果,不僅需要這樣一段程序,更重要的還需要色彩與深度相關的視頻作爲輔助~下面是原始視頻圖片
總結:之前我使用THREE.point創建了很多個點,然後人爲排列它們的位置,使其組成一幅圖片,優點是方便了對於每一個粒子對象的控制,缺點是組成的圖片間距需要自己調整,容易出現水波紋的現象。與我不同的是官方使用了BufferGeometry對象,方便了着色器的對其的控制,這種方法更加適合圖片、視頻紋理特效的呈現。