對threejs官方案例webgl_kinect的思考

在上次按照自己的想法使用粒子系統對圖片進行處理之後,我最近又看到了官方案例中,使用粒子使視頻呈現出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對象,方便了着色器的對其的控制,這種方法更加適合圖片、視頻紋理特效的呈現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章