浅谈Three.js源码-render之WebGLAttributes.js

/**
 * @author mrdoob / http://mrdoob.com/
 */

function WebGLAttributes( gl ) {            //传入WebGL上下文

   var buffers = {};                    //用来存储传入渲染管线的数据

   function createBuffer( attribute, bufferType ) {
      /*bufferType表示数据的类型,可以选择的值有GL_ARRAY_BUFFER和GL_ELEMENT_ARRAY_BUFFER。
      1.GL_ARRAY_BUFFER代表存储数据的数组中存储的是顶点数据,
      2.GL_ELEMENT_ARRAY_BUFFER代表数组中存储的各个定点的索引
      */

      var array = attribute.array;             //attribute.array中存储的是几何对象中已经排列好的顶点坐标位置
      var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;/*vbo(顶点缓存技术)的相关设置, gl.STATIC_DRAW是将数据存储放置在显存中
       当值为gl.DYNAMIC_DRAW时,数据被存储在系统或AGP(加速图形接口)中,方便对其进行修改和读取,可能这里读者会觉得比较复杂,但是毕竟它很大程度上较少了GPU和存储之间的数据交互次数*/

      var buffer = gl.createBuffer();          //创建一个缓存对象

      gl.bindBuffer( bufferType, buffer );      //激活缓冲区对象
      gl.bufferData( bufferType, array, usage ); //用数据分配和初始化缓冲区对象 array:用于初始化缓冲区的对象

      attribute.onUploadCallback(); //??????

      var type = gl.FLOAT;                  //type表示当前数据中每个元素的类型,将其默认为gl.FLOAT

      /*根据数据存储的数组类型,设置type值。
       我们平时使用的Array对象说它是数组,其实是一个从哈希表扩展的结构体。因此它可以提供push、splice等一些列操作。
       这就意味着他们的效率是很低的。在JavaScript中也可以创建真正的数组,那就是强类型数组。
       这个概念在以前的JavaScript中是没有的,由于现在JavaScript的发展,它变得可以调用一些系统底层的东西比如WebGL。
       这些底层的操作需要直接访问内存,而JavaScript本身的Array在内存中是分散无法与底层操作对接,因此引入了这些强类型的数组。
       原文链接:https://www.web-tinker.com/article/20101.html
      * */

      if ( array instanceof Float32Array ) {

         type = gl.FLOAT;

      } else if ( array instanceof Float64Array ) {

         console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );

      } else if ( array instanceof Uint16Array ) {

         type = gl.UNSIGNED_SHORT;

      } else if ( array instanceof Int16Array ) {

         type = gl.SHORT;

      } else if ( array instanceof Uint32Array ) {

         type = gl.UNSIGNED_INT;

      } else if ( array instanceof Int32Array ) {

         type = gl.INT;

      } else if ( array instanceof Int8Array ) {

         type = gl.BYTE;

      } else if ( array instanceof Uint8Array ) {

         type = gl.UNSIGNED_BYTE;

      }

      return {
         buffer: buffer,
         type: type,
         bytesPerElement: array.BYTES_PER_ELEMENT,
         version: attribute.version//这里是为了标记此属性的缓存是否需要进行更新,如果attribute的version值大于buffer的version值,则说明需要缓存数据需要更新
 
      };     
	
/*TypedArray.BYTES_PER_ELEMENT 属性代表了强类型数组中每个元素所占用的字节数。
       强类型数组对象用来解释为单个元素的字节数是不一样的。常量 BYTES_PER_ELEMENT 表示了特定强类型数组中每个元素所占用的字节数。
       各类型其BYTES_PER_ELEMENT值如下所示。

       Int8Array.BYTES_PER_ELEMENT;         // 1
       Uint8Array.BYTES_PER_ELEMENT;        // 1
       Uint8ClampedArray.BYTES_PER_ELEMENT; // 1
       Int16Array.BYTES_PER_ELEMENT;        // 2
       Uint16Array.BYTES_PER_ELEMENT;       // 2
       Int32Array.BYTES_PER_ELEMENT;        // 4
       Uint32Array.BYTES_PER_ELEMENT;       // 4
       Float32Array.BYTES_PER_ELEMENT;      // 4
       Float64Array.BYTES_PER_ELEMENT;      // 8
      出自:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/BYTES_PER_ELEMENT
      * */
   }

   function updateBuffer( buffer, attribute, bufferType ) {

      var array = attribute.array;//拿到存储数据的数组
      var updateRange = attribute.updateRange;//数组中需要更新的范围(updateRange.offset代表需要更新数据的偏移量和总个数)


      gl.bindBuffer( bufferType, buffer ); //确定当前操作的缓冲区

      if ( attribute.dynamic === false ) {//如果此项属性不是动态的,则直接将数据进行上传

         gl.bufferData( bufferType, array, gl.STATIC_DRAW );

      } else if ( updateRange.count === - 1 ) {//如果没有规定需要更新的范围,则将整个数组进行更新

         // Not using update ranges

         gl.bufferSubData( bufferType, 0, array );

      } else if ( updateRange.count === 0 ) {

         console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );

      } else {

         gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
            array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );//假设已经在用用程序的一个缓冲区中准备了相同类型的数据,glBufferSubData()将用我们提供的数据替换被绑定的缓冲区对象的一些数据子集。

         updateRange.count = -1; // reset range

      }

   }

   //

   function get( attribute ) {

      if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;

      return buffers[ attribute.uuid ];

   }

   function remove( attribute ) {

      if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
      
      var data = buffers[ attribute.uuid ];

      if ( data ) {

         gl.deleteBuffer( data.buffer );                   //在渲染管线中删除相关数据

         delete buffers[ attribute.uuid ];                 //清除javascript程序中用来存储数据的数组对象



      }

   }

   function update( attribute, bufferType ) {//更新数据缓存的方法

      if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;//??????这句不太明白什么意思,以后研究清楚了再编辑。。。。。。。。。。

      var data = buffers[ attribute.uuid ];//获取当前的数据数组 uuid是唯一标识对象的一种形式,通过uuid可以快速对数据缓存对象进行操作

      if ( data === undefined ) {//如果数据数组不存在,则直接进行创建

         buffers[ attribute.uuid ] = createBuffer( attribute, bufferType );

      } else if ( data.version < attribute.version ) {//如果数据数组存在,并且attribute.version的值高于了data.version,说明attribute中的相关数据需要进行更新

         updateBuffer( data.buffer, attribute, bufferType );

         data.version = attribute.version;

      }

   }

   return {

      get: get,
      remove: remove,
      update: update

   };

}
	export { WebGLAttributes };//使用export语法将WebGLAttributes暴露出来,在其他脚本中可以引入和操作
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值