Threejs 源码解析(WebGLState.js)重要

解释有什么问题,说一下,不喜勿喷,
转载请注明:七岁 https://blog.csdn.net/qq_25909453/article/details/82704620







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

import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, DoubleSide, BackSide } from '../../constants.js';
import { Vector4 } from '../../math/Vector4.js';

function WebGLState( gl, extensions, utils, capabilities ) {
    /**
     * 颜色缓冲
     * @returns {{setMask: setMask, setLocked: setLocked, setClear: setClear, reset: reset}}
     * @constructor
     */
   function ColorBuffer() {
        //是否加锁
      var locked = false;

      var color = new Vector4();
        //当前能否写入颜色帧缓冲区
        var currentColorMask = null;
        //当前清除颜色,清除后的背景颜色
        var currentColorClear = new Vector4( 0, 0, 0, 0 );

      return {
            /**
             * 设置能否写入颜色帧缓冲区
             * @param colorMask
             */
         setMask: function ( colorMask ) {
                //如果用户改变了颜色帧缓冲区的写入状态并且没有加锁
            if ( currentColorMask !== colorMask && ! locked ) {
                    //重新设置颜色帧缓冲区的写入状态
               gl.colorMask( colorMask, colorMask, colorMask, colorMask );
                    //记录当前颜色帧缓冲区的状态
                    currentColorMask = colorMask;

            }

         },
            //设置是否加锁,如果lock为true,则表示一直已经加锁,颜色帧缓冲区的写入状态不能改变
         setLocked: function ( lock ) {

            locked = lock;

         },
            //设置背景颜色;premultipliedAlpha表示是否需要增加透明效果
         setClear: function ( r, g, b, a, premultipliedAlpha ) {

            if ( premultipliedAlpha === true ) {

               r *= a; g *= a; b *= a;

            }

            color.set( r, g, b, a );

            if ( currentColorClear.equals( color ) === false ) {

               gl.clearColor( r, g, b, a );
               currentColorClear.copy( color );

            }

         },
            //重置相关设置
         reset: function () {

            locked = false;

            currentColorMask = null;
            currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state

         }

      };

   }
    //关于深度缓冲的设置
   function DepthBuffer() {
        //是否加锁
      var locked = false;
        //表示是否可以对深度缓冲区进行修改
      var currentDepthMask = null;
      var currentDepthFunc = null;
      var currentDepthClear = null;

      return {
            //设置是否开启深度检测
         setTest: function ( depthTest ) {

            if ( depthTest ) {

               enable( gl.DEPTH_TEST );

            } else {

               disable( gl.DEPTH_TEST );

            }

         },
            //设置是否可以对深度缓冲区进行修改
         setMask: function ( depthMask ) {

            if ( currentDepthMask !== depthMask && ! locked ) {

               gl.depthMask( depthMask );
               currentDepthMask = depthMask;

            }

         },
            /**
             * 此函数的作用是确定深度值的比较方式。
             每画一个物体,设备中将存储每个像素点的深度值,如果需要新绘制一个物体A,则对应像素处的深度值需要
             和深度缓冲区的值进行比较,默认情况下,gl.depthFunc( GL_LESS),也就是在对于某个像素处,A的深度值小于
             帧缓冲区中对应的深度值才会取A的颜色,否则不会发生改变
             * @param depthFunc
             */
         setFunc: function ( depthFunc ) {

            if ( currentDepthFunc !== depthFunc ) {

               if ( depthFunc ) {

                  switch ( depthFunc ) {

                     case NeverDepth:

                        gl.depthFunc( gl.NEVER );
                        break;

                     case AlwaysDepth:

                        gl.depthFunc( gl.ALWAYS );
                        break;

                     case LessDepth:

                        gl.depthFunc( gl.LESS );
                        break;

                     case LessEqualDepth:

                        gl.depthFunc( gl.LEQUAL );
                        break;

                     case EqualDepth:

                        gl.depthFunc( gl.EQUAL );
                        break;

                     case GreaterEqualDepth:

                        gl.depthFunc( gl.GEQUAL );
                        break;

                     case GreaterDepth:

                        gl.depthFunc( gl.GREATER );
                        break;

                     case NotEqualDepth:

                        gl.depthFunc( gl.NOTEQUAL );
                        break;

                     default:

                        gl.depthFunc( gl.LEQUAL );

                  }

               } else {

                  gl.depthFunc( gl.LEQUAL );

               }

               currentDepthFunc = depthFunc;

            }

         },
            //表示深度缓冲区设置是否可以进行更改
         setLocked: function ( lock ) {

            locked = lock;

         },
            //清除深度缓冲区,depth值为要设置的深度缓冲区的值,取值范围为【0-1】
         setClear: function ( depth ) {

            if ( currentDepthClear !== depth ) {

               gl.clearDepth( depth );
               currentDepthClear = depth;

            }

         },
            //重置关于深度缓冲的相关设置
         reset: function () {

            locked = false;

            currentDepthMask = null;
            currentDepthFunc = null;
            currentDepthClear = null;

         }

      };

   }
    /**
     * 模板缓冲的相关设置,模板缓冲的值取值范围为[0-2的n次方-1],其中n代表模板缓冲值在2进制下
     * @returns {{setTest: setTest, setMask: setMask, setFunc: setFunc, setOp: setOp, setLocked: setLocked, setClear: setClear, reset: reset}}
     * @constructor
     * 相关介绍;http://blog.csdn.net/wangdingqiaoit/article/details/52143197
     */
   function StencilBuffer() {

      var locked = false;

      var currentStencilMask = null;
      var currentStencilFunc = null;
      var currentStencilRef = null;
      var currentStencilFuncMask = null;
      var currentStencilFail = null;
      var currentStencilZFail = null;
      var currentStencilZPass = null;
      var currentStencilClear = null;

      return {
            //是否开启模板测试
         setTest: function ( stencilTest ) {

            if ( stencilTest ) {

               enable( gl.STENCIL_TEST );

            } else {

               disable( gl.STENCIL_TEST );

            }

         },
            //设置是否可以对模板缓冲区进行写入和修改
         setMask: function ( stencilMask ) {

            if ( currentStencilMask !== stencilMask && ! locked ) {

               gl.stencilMask( stencilMask );
               currentStencilMask = stencilMask;

            }

         },
            //设置模板缓冲的比较方式
         setFunc: function ( stencilFunc, stencilRef, stencilMask ) {

            if ( currentStencilFunc !== stencilFunc ||
                 currentStencilRef     !== stencilRef     ||
                 currentStencilFuncMask !== stencilMask ) {

               gl.stencilFunc( stencilFunc, stencilRef, stencilMask );

               currentStencilFunc = stencilFunc;
               currentStencilRef = stencilRef;
               currentStencilFuncMask = stencilMask;

            }

         },
            /*stencilFail代表的是模板测试失败,对应模板缓冲区的值应该进行的操作,可选的值有
                GL_KEEP,GL_ZERO,GL_REPLACE,GL_INCR,GL_INCR_WRAP,GL_DECR,GL_DECR_WRAP,GL_INVERT
                stencilZFail代表的是模板测试成功,但是深度检测没有通过后的操作,可选的值和上面的相同
                stencilZPass代表的是模板测试和深度检测都通过时,可选择的值和上面相同*/
         setOp: function ( stencilFail, stencilZFail, stencilZPass ) {

            if ( currentStencilFail     !== stencilFail   ||
                 currentStencilZFail !== stencilZFail ||
                 currentStencilZPass !== stencilZPass ) {

               gl.stencilOp( stencilFail, stencilZFail, stencilZPass );

               currentStencilFail = stencilFail;
               currentStencilZFail = stencilZFail;
               currentStencilZPass = stencilZPass;

            }

         },

         setLocked: function ( lock ) {

            locked = lock;

         },

         setClear: function ( stencil ) {

            if ( currentStencilClear !== stencil ) {

               gl.clearStencil( stencil );
               currentStencilClear = stencil;

            }

         },

         reset: function () {

            locked = false;

            currentStencilMask = null;
            currentStencilFunc = null;
            currentStencilRef = null;
            currentStencilFuncMask = null;
            currentStencilFail = null;
            currentStencilZFail = null;
            currentStencilZPass = null;
            currentStencilClear = null;

         }

      };

   }

   //

   var colorBuffer = new ColorBuffer();
   var depthBuffer = new DepthBuffer();
   var stencilBuffer = new StencilBuffer();
    //从系统最多支持的顶点属性个数
   var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
   var newAttributes = new Uint8Array( maxVertexAttributes );
   var enabledAttributes = new Uint8Array( maxVertexAttributes );
   var attributeDivisors = new Uint8Array( maxVertexAttributes );

   var enabledCapabilities = {};

   var compressedTextureFormats = null;

   var currentProgram = null;

   var currentBlending = null;
   var currentBlendEquation = null;
   var currentBlendSrc = null;
   var currentBlendDst = null;
   var currentBlendEquationAlpha = null;
   var currentBlendSrcAlpha = null;
   var currentBlendDstAlpha = null;
   var currentPremultipledAlpha = false;

   var currentFlipSided = null;
   var currentCullFace = null;

   var currentLineWidth = null;

   var currentPolygonOffsetFactor = null;
   var currentPolygonOffsetUnits = null;
    //单个片段着色器能访问的纹理单元数,最低16,一般16或32
   var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );

   var lineWidthAvailable = false;
   var version = 0;
   var glVersion = gl.getParameter( gl.VERSION );

   if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
        //获取当前WebGL的版本
      version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
      //可用线宽度
      lineWidthAvailable = ( version >= 1.0 );

   } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {

      version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
      lineWidthAvailable = ( version >= 2.0 );

   }

   var currentTextureSlot = null;
   var currentBoundTextures = {};

   var currentScissor = new Vector4();
   var currentViewport = new Vector4();

    /**
    * 创建纹理
     * @param type
     * @param target
     * @param count
     * @returns {*}
     */
   function createTexture( type, target, count ) {

      var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
        //创建纹理单元
        var texture = gl.createTexture();
        //将图片和纹理单元绑定
      gl.bindTexture( type, texture );
        /**
         * 纹理映射;
         * 官方文档:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/texParameter
         * 相关资料:https://www.web-tinker.com/article/20163.html
         */
        //设置纹理缩小取样的方式为最近点采样
        gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
        //设置纹理扩大取样的方式为最近点采样
        gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );

      for ( var i = 0; i < count; i ++ ) {

         gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );

      }

      return texture;

   }

   var emptyTextures = {};
   emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );//初始化2D纹理
   emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );//初始化立方体纹理

   // init
   //设置清除颜色
   colorBuffer.setClear( 0, 0, 0, 1 );
   //设置深度值
   depthBuffer.setClear( 1 );
   //设置模板值
   stencilBuffer.setClear( 0 );

    /**
    * 开启深度检测
     */
   enable( gl.DEPTH_TEST );
   depthBuffer.setFunc( LessEqualDepth );
    /**
    *     是否开启正反面转换,通常情况下,当观察者从正面看三角形时ti,三角形的构造方式是逆时针的。
    *     这样程序会将所有顺时针构造的三角形面当作被遮挡的面进行剔除。从而很大程度上避免了无用的系统开销
     */
   setFlipSided( false );
    /**设置剪裁面
    * 设置背面剪裁的方式,一共有三种(1.只显示正面,2.只显示背面,3同时显示正面和背面)
     */
   setCullFace( CullFaceBack );
   //开启背面剪裁
   enable( gl.CULL_FACE );
   //开启混合
   enable( gl.BLEND );
   //设置混合方式
   setBlending( NormalBlending );

   //
    /**
    * 初始化属性数组,
     */
   function initAttributes() {

      for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {

         newAttributes[ i ] = 0;

      }

   }

    /**
    * 开启对应的属性
     * @param attribute
     */
   function enableAttribute( attribute ) {

      enableAttributeAndDivisor( attribute, 0 );

   }

    /**
    * 开启对应属性数组
     * @param attribute 属性
     * @param meshPerAttribute 每个属性的相关设置
     */
   function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
      //attribute 是属性名称,用属性名称做Key, 1表示开启
      newAttributes[ attribute ] = 1;

        /**
       * 如果当前没有开启次属性,那就开启它
         */
      if ( enabledAttributes[ attribute ] === 0 ) {

         gl.enableVertexAttribArray( attribute );//开启对应的属性
         enabledAttributes[ attribute ] = 1;//设置为开始,1表示已经开启

      }
        /**
       * 开启扩展
         */
      if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
            /**
          * 是否是webGL2 ,是就直接使用上下文,不是就进行扩展
             */
         var extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );

         extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
         attributeDivisors[ attribute ] = meshPerAttribute;

      }

   }

    /**注销属性
    * 把没开启的属性设置成关闭
     */
   function disableUnusedAttributes() {

      for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {

         if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {

            gl.disableVertexAttribArray( i );
            enabledAttributes[ i ] = 0;

         }

      }

   }

    /**
    * 开启属性
     * @param id
     */
   function enable( id ) {

      if ( enabledCapabilities[ id ] !== true ) {

         gl.enable( id );
         enabledCapabilities[ id ] = true;

      }

   }

    /**
    * 注销属性
     * @param id
     */
   function disable( id ) {

      if ( enabledCapabilities[ id ] !== false ) {

         gl.disable( id );
         enabledCapabilities[ id ] = false;

      }

   }
   //得到压缩文本格式
   function getCompressedTextureFormats() {

      if ( compressedTextureFormats === null ) {

         compressedTextureFormats = [];

         if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
              extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
              extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
              extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
            //返回压缩的纹理格式,见文档:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter
            var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );

            for ( var i = 0; i < formats.length; i ++ ) {

               compressedTextureFormats.push( formats[ i ] );

            }

         }

      }

      return compressedTextureFormats;

   }

    /**
    * 开启程序对象,如果当前程序对象等于program,则开启,返回true,否则返回false
     * @param program
     * @returns {boolean}
     */
   function useProgram( program ) {

      if ( currentProgram !== program ) {

         gl.useProgram( program );

         currentProgram = program;

         return true;

      }

      return false;

   }

    /**
    * 设置颜色混合的多种方式
     * @param blending
     * @param blendEquation
     * @param blendSrc
     * @param blendDst
     * @param blendEquationAlpha
     * @param blendSrcAlpha
     * @param blendDstAlpha
     * @param premultipliedAlpha
     */
   function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {

      if ( blending !== NoBlending ) {

         enable( gl.BLEND );

      } else {

         disable( gl.BLEND );

      }

      if ( blending !== CustomBlending ) {

         if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {

            switch ( blending ) {

               case AdditiveBlending:

                  if ( premultipliedAlpha ) {

                     gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
                     gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );

                  } else {

                     gl.blendEquation( gl.FUNC_ADD );
                     gl.blendFunc( gl.SRC_ALPHA, gl.ONE );

                  }
                  break;

               case SubtractiveBlending:

                  if ( premultipliedAlpha ) {

                     gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
                     gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );

                  } else {

                     gl.blendEquation( gl.FUNC_ADD );
                     gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );

                  }
                  break;

               case MultiplyBlending:

                  if ( premultipliedAlpha ) {

                     gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
                     gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );

                  } else {

                     gl.blendEquation( gl.FUNC_ADD );
                     gl.blendFunc( gl.ZERO, gl.SRC_COLOR );

                  }
                  break;

               default:

                  if ( premultipliedAlpha ) {

                     gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
                     gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );

                  } else {

                     gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
                     gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );

                  }

            }

         }

         currentBlendEquation = null;
         currentBlendSrc = null;
         currentBlendDst = null;
         currentBlendEquationAlpha = null;
         currentBlendSrcAlpha = null;
         currentBlendDstAlpha = null;

      } else {

         blendEquationAlpha = blendEquationAlpha || blendEquation;
         blendSrcAlpha = blendSrcAlpha || blendSrc;
         blendDstAlpha = blendDstAlpha || blendDst;

         if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {

            gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) );

            currentBlendEquation = blendEquation;
            currentBlendEquationAlpha = blendEquationAlpha;

         }

         if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {

            gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) );

            currentBlendSrc = blendSrc;
            currentBlendDst = blendDst;
            currentBlendSrcAlpha = blendSrcAlpha;
            currentBlendDstAlpha = blendDstAlpha;

         }

      }

      currentBlending = blending;
      currentPremultipledAlpha = premultipliedAlpha;

   }

    /**
    * 设置材质
     * @param material
     * @param frontFaceCW
     */
   function setMaterial( material, frontFaceCW ) {

      material.side === DoubleSide
         ? disable( gl.CULL_FACE )
         : enable( gl.CULL_FACE );

      var flipSided = ( material.side === BackSide );
      if ( frontFaceCW ) flipSided = ! flipSided;

      setFlipSided( flipSided );

      ( material.blending === NormalBlending && material.transparent === false )
         ? setBlending( NoBlending )
         : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );

      depthBuffer.setFunc( material.depthFunc );
      depthBuffer.setTest( material.depthTest );
      depthBuffer.setMask( material.depthWrite );
      colorBuffer.setMask( material.colorWrite );

      setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );

   }

   //
    /**
    * 设置多边形的绕线方式,这种方式用来设置那一面是正面,
     * @param flipSided
     */
   function setFlipSided( flipSided ) {

      if ( currentFlipSided !== flipSided ) {

         if ( flipSided ) {

            gl.frontFace( gl.CW );//顺时针

         } else {

            gl.frontFace( gl.CCW );//逆时针

         }

         currentFlipSided = flipSided;

      }

   }

    /**
    *裁剪面,通过裁剪没用的面达到性能提高的目的
     * @param cullFace 裁剪面参数
    * 文档见:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/cullFace
     */
   function setCullFace( cullFace ) {

      if ( cullFace !== CullFaceNone ) {
         //激活裁剪多边形
         enable( gl.CULL_FACE );

         if ( cullFace !== currentCullFace ) {

            if ( cullFace === CullFaceBack ) {

               gl.cullFace( gl.BACK );//裁剪掉背面

            } else if ( cullFace === CullFaceFront ) {

               gl.cullFace( gl.FRONT );//裁剪掉前面

            } else {

               gl.cullFace( gl.FRONT_AND_BACK );//前后两面都裁剪

            }

         }

      } else {

         disable( gl.CULL_FACE );//不进行裁剪,注销裁剪功能

      }

      currentCullFace = cullFace;

   }

    /**
    * 设置线的宽度,没什么用,现在的webgl版本,包括OpenGL ES 2/3  最大最小宽度都是1;总的来说设置不了
     * @param width
     */
   function setLineWidth( width ) {

      if ( width !== currentLineWidth ) {

         if ( lineWidthAvailable ) gl.lineWidth( width );

         currentLineWidth = width;

      }

   }

    /**
    * 设置多边形的深度偏移
     * @param polygonOffset
     * @param factor
     * @param units
     */
   function setPolygonOffset( polygonOffset, factor, units ) {

      if ( polygonOffset ) {
         //开启多边形的偏移,应该是深度偏移,原文档,原话Activates adding an offset to depth values of polygon's fragments. See
         enable( gl.POLYGON_OFFSET_FILL );

         if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {

            gl.polygonOffset( factor, units );

            currentPolygonOffsetFactor = factor;
            currentPolygonOffsetUnits = units;

         }

      } else {

         disable( gl.POLYGON_OFFSET_FILL );

      }

   }

    /**
    * 设置模板测试
     * @param scissorTest
     */
   function setScissorTest( scissorTest ) {

      if ( scissorTest ) {
            /**
          * Activates the scissor test that discards fragments that are outside of the scissor rectangle
             */
         enable( gl.SCISSOR_TEST );

      } else {

         disable( gl.SCISSOR_TEST );

      }

   }

   // texture
    /**
    * 激活指定纹理
     * @param webglSlot
     */
   function activeTexture( webglSlot ) {
      //webglSlot 等于unfefined 时,指定最大纹理
      if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;

      if ( currentTextureSlot !== webglSlot ) {

         gl.activeTexture( webglSlot );
         currentTextureSlot = webglSlot;

      }

   }

    /**
    * 绑定纹理
     * @param webglType  (gl.TEXTURE_2D、gl.TEXTURE_CUBE_MAP, gl.TEXTURE_3D, or gl.TEXTURE_2D_ARRAY.)
     * @param webglTexture  纹理对象
     */
   function bindTexture( webglType, webglTexture ) {

      if ( currentTextureSlot === null ) {

         activeTexture();

      }

      var boundTexture = currentBoundTextures[ currentTextureSlot ];

      if ( boundTexture === undefined ) {

         boundTexture = { type: undefined, texture: undefined };
         currentBoundTextures[ currentTextureSlot ] = boundTexture;

      }

      if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
         //webglTexture 如果为空,则使用emptyTextures[ webglType ]
         gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );

         boundTexture.type = webglType;
         boundTexture.texture = webglTexture;

      }

   }

    /**
    * 指定颜色格式
     */
   function compressedTexImage2D() {

      try {
         //指定压缩格式的三维纹理图像
         //文档见:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/compressedTexImage2D
         gl.compressedTexImage2D.apply( gl, arguments );

      } catch ( error ) {

         console.error( 'THREE.WebGLState:', error );

      }

   }

    /**
    * 指定一个纹理图像,也就是把图片设置到纹理中
    * 文档见:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D
     */
   function texImage2D() {

      try {

         gl.texImage2D.apply( gl, arguments );

      } catch ( error ) {

         console.error( 'THREE.WebGLState:', error );

      }

   }

   //
    /**
    * 设置模板
     * @param scissor
     */
   function scissor( scissor ) {

      if ( currentScissor.equals( scissor ) === false ) {
         //设置模板的大小,一般用来把其它场景作为纹理使用时,就会用到模板缓冲区
         gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
         currentScissor.copy( scissor );

      }

   }

    /**
    * 设置位置大小,这是webgl里的绘制大小,把场景作为纹理使用时可使用viewport来调节纹理的大小
     * @param viewport
     */
   function viewport( viewport ) {

      if ( currentViewport.equals( viewport ) === false ) {

         gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
         currentViewport.copy( viewport );

      }

   }

   //
    /**
    * 重置
     */
   function reset() {

      for ( var i = 0; i < enabledAttributes.length; i ++ ) {

         if ( enabledAttributes[ i ] === 1 ) {
            //注销属性
            gl.disableVertexAttribArray( i );
            enabledAttributes[ i ] = 0;

         }

      }

      enabledCapabilities = {};

      compressedTextureFormats = null;

      currentTextureSlot = null;
      currentBoundTextures = {};

      currentProgram = null;

      currentBlending = null;

      currentFlipSided = null;
      currentCullFace = null;

      colorBuffer.reset();//颜色缓冲区重置
      depthBuffer.reset();//深度缓冲区重置
      stencilBuffer.reset();//模板缓冲区重置

   }

   return {

      buffers: {
         color: colorBuffer,
         depth: depthBuffer,
         stencil: stencilBuffer
      },

      initAttributes: initAttributes,
      enableAttribute: enableAttribute,
      enableAttributeAndDivisor: enableAttributeAndDivisor,
      disableUnusedAttributes: disableUnusedAttributes,
      enable: enable,
      disable: disable,
      getCompressedTextureFormats: getCompressedTextureFormats,

      useProgram: useProgram,

      setBlending: setBlending,
      setMaterial: setMaterial,

      setFlipSided: setFlipSided,
      setCullFace: setCullFace,

      setLineWidth: setLineWidth,
      setPolygonOffset: setPolygonOffset,

      setScissorTest: setScissorTest,

      activeTexture: activeTexture,
      bindTexture: bindTexture,
      compressedTexImage2D: compressedTexImage2D,
      texImage2D: texImage2D,

      scissor: scissor,
      viewport: viewport,

      reset: reset

   };

}


export { WebGLState };

你可能感兴趣的:(threejs,源码解析)