123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- /**
- * @author mrdoob / http://mrdoob.com/
- */
- THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
- var _this = this;
- var newAttributes = new Uint8Array( 16 );
- var enabledAttributes = new Uint8Array( 16 );
- var attributeDivisors = new Uint8Array( 16 );
- var capabilities = {};
- var compressedTextureFormats = null;
- var currentBlending = null;
- var currentBlendEquation = null;
- var currentBlendSrc = null;
- var currentBlendDst = null;
- var currentBlendEquationAlpha = null;
- var currentBlendSrcAlpha = null;
- var currentBlendDstAlpha = null;
- var currentDepthFunc = null;
- var currentDepthWrite = null;
- var currentColorWrite = null;
- var currentFlipSided = null;
- var currentLineWidth = null;
- var currentPolygonOffsetFactor = null;
- var currentPolygonOffsetUnits = null;
- var currentScissorTest = null;
- var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
- var currentTextureSlot = undefined;
- var currentBoundTextures = {};
- this.init = function () {
- gl.clearColor( 0, 0, 0, 1 );
- gl.clearDepth( 1 );
- gl.clearStencil( 0 );
- this.enable( gl.DEPTH_TEST );
- gl.depthFunc( gl.LEQUAL );
- gl.frontFace( gl.CCW );
- gl.cullFace( gl.BACK );
- this.enable( gl.CULL_FACE );
- this.enable( gl.BLEND );
- gl.blendEquation( gl.FUNC_ADD );
- gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
- };
- this.initAttributes = function () {
- for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
- newAttributes[ i ] = 0;
- }
- };
- this.enableAttribute = function ( attribute ) {
- newAttributes[ attribute ] = 1;
- if ( enabledAttributes[ attribute ] === 0 ) {
- gl.enableVertexAttribArray( attribute );
- enabledAttributes[ attribute ] = 1;
- }
- if ( attributeDivisors[ attribute ] !== 0 ) {
- var extension = extensions.get( 'ANGLE_instanced_arrays' );
- extension.vertexAttribDivisorANGLE( attribute, 0 );
- attributeDivisors[ attribute ] = 0;
- }
- };
- this.enableAttributeAndDivisor = function ( attribute, meshPerAttribute, extension ) {
- newAttributes[ attribute ] = 1;
- if ( enabledAttributes[ attribute ] === 0 ) {
- gl.enableVertexAttribArray( attribute );
- enabledAttributes[ attribute ] = 1;
- }
- if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
- extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
- attributeDivisors[ attribute ] = meshPerAttribute;
- }
- };
- this.disableUnusedAttributes = function () {
- for ( var i = 0, l = enabledAttributes.length; i < l; i ++ ) {
- if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
- gl.disableVertexAttribArray( i );
- enabledAttributes[ i ] = 0;
- }
- }
- };
- this.enable = function ( id ) {
- if ( capabilities[ id ] !== true ) {
- gl.enable( id );
- capabilities[ id ] = true;
- }
- };
- this.disable = function ( id ) {
- if ( capabilities[ id ] !== false ) {
- gl.disable( id );
- capabilities[ id ] = false;
- }
- };
- this.getCompressedTextureFormats = function () {
- if ( compressedTextureFormats === null ) {
- compressedTextureFormats = [];
- if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
- extensions.get( 'WEBGL_compressed_texture_s3tc' ) ) {
- var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
- for ( var i = 0; i < formats.length; i ++ ) {
- compressedTextureFormats.push( formats[ i ] );
- }
- }
- }
- return compressedTextureFormats;
- };
- this.setBlending = function ( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha ) {
- if ( blending === THREE.NoBlending ) {
- this.disable( gl.BLEND );
- } else {
- this.enable( gl.BLEND );
- }
- if ( blending !== currentBlending ) {
- if ( blending === THREE.AdditiveBlending ) {
- gl.blendEquation( gl.FUNC_ADD );
- gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
- } else if ( blending === THREE.SubtractiveBlending ) {
- // TODO: Find blendFuncSeparate() combination
- gl.blendEquation( gl.FUNC_ADD );
- gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
- } else if ( blending === THREE.MultiplyBlending ) {
- // TODO: Find blendFuncSeparate() combination
- gl.blendEquation( gl.FUNC_ADD );
- gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
- } 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 );
- }
- currentBlending = blending;
- }
- if ( blending === THREE.CustomBlending ) {
- blendEquationAlpha = blendEquationAlpha || blendEquation;
- blendSrcAlpha = blendSrcAlpha || blendSrc;
- blendDstAlpha = blendDstAlpha || blendDst;
- if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
- gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) );
- currentBlendEquation = blendEquation;
- currentBlendEquationAlpha = blendEquationAlpha;
- }
- if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
- gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) );
- currentBlendSrc = blendSrc;
- currentBlendDst = blendDst;
- currentBlendSrcAlpha = blendSrcAlpha;
- currentBlendDstAlpha = blendDstAlpha;
- }
- } else {
- currentBlendEquation = null;
- currentBlendSrc = null;
- currentBlendDst = null;
- currentBlendEquationAlpha = null;
- currentBlendSrcAlpha = null;
- currentBlendDstAlpha = null;
- }
- };
- this.setDepthFunc = function ( depthFunc ) {
- if ( currentDepthFunc !== depthFunc ) {
- if ( depthFunc ) {
- switch ( depthFunc ) {
- case THREE.NeverDepth:
- gl.depthFunc( gl.NEVER );
- break;
- case THREE.AlwaysDepth:
- gl.depthFunc( gl.ALWAYS );
- break;
- case THREE.LessDepth:
- gl.depthFunc( gl.LESS );
- break;
- case THREE.LessEqualDepth:
- gl.depthFunc( gl.LEQUAL );
- break;
- case THREE.EqualDepth:
- gl.depthFunc( gl.EQUAL );
- break;
- case THREE.GreaterEqualDepth:
- gl.depthFunc( gl.GEQUAL );
- break;
- case THREE.GreaterDepth:
- gl.depthFunc( gl.GREATER );
- break;
- case THREE.NotEqualDepth:
- gl.depthFunc( gl.NOTEQUAL );
- break;
- default:
- gl.depthFunc( gl.LEQUAL );
- }
- } else {
- gl.depthFunc( gl.LEQUAL );
- }
- currentDepthFunc = depthFunc;
- }
- };
- this.setDepthTest = function ( depthTest ) {
- if ( depthTest ) {
- this.enable( gl.DEPTH_TEST );
- } else {
- this.disable( gl.DEPTH_TEST );
- }
- };
- this.setDepthWrite = function ( depthWrite ) {
- if ( currentDepthWrite !== depthWrite ) {
- gl.depthMask( depthWrite );
- currentDepthWrite = depthWrite;
- }
- };
- this.setColorWrite = function ( colorWrite ) {
- if ( currentColorWrite !== colorWrite ) {
- gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite );
- currentColorWrite = colorWrite;
- }
- };
- this.setFlipSided = function ( flipSided ) {
- if ( currentFlipSided !== flipSided ) {
- if ( flipSided ) {
- gl.frontFace( gl.CW );
- } else {
- gl.frontFace( gl.CCW );
- }
- currentFlipSided = flipSided;
- }
- };
- this.setLineWidth = function ( width ) {
- if ( width !== currentLineWidth ) {
- gl.lineWidth( width );
- currentLineWidth = width;
- }
- };
- this.setPolygonOffset = function ( polygonOffset, factor, units ) {
- if ( polygonOffset ) {
- this.enable( gl.POLYGON_OFFSET_FILL );
- } else {
- this.disable( gl.POLYGON_OFFSET_FILL );
- }
- if ( polygonOffset && ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) ) {
- gl.polygonOffset( factor, units );
- currentPolygonOffsetFactor = factor;
- currentPolygonOffsetUnits = units;
- }
- };
- this.getScissorTest = function () {
- return currentScissorTest;
- };
- this.setScissorTest = function ( scissorTest ) {
- currentScissorTest = scissorTest;
- if ( scissorTest ) {
- this.enable( gl.SCISSOR_TEST );
- } else {
- this.disable( gl.SCISSOR_TEST );
- }
- };
- // texture
- this.activeTexture = function ( webglSlot ) {
- if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
- if ( currentTextureSlot !== webglSlot ) {
- gl.activeTexture( webglSlot );
- currentTextureSlot = webglSlot;
- }
- }
- this.bindTexture = function ( webglType, webglTexture ) {
- if ( currentTextureSlot === undefined ) {
- _this.activeTexture();
- }
- var boundTexture = currentBoundTextures[ currentTextureSlot ];
- if ( boundTexture === undefined ) {
- boundTexture = { type: undefined, texture: undefined };
- currentBoundTextures[ currentTextureSlot ] = boundTexture;
- }
- if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
- gl.bindTexture( webglType, webglTexture );
- boundTexture.type = webglType;
- boundTexture.texture = webglTexture;
- }
- };
- this.compressedTexImage2D = function () {
- try {
- gl.compressedTexImage2D.apply( gl, arguments );
- } catch ( error ) {
- console.error( error );
- }
- };
- this.texImage2D = function () {
- try {
- gl.texImage2D.apply( gl, arguments );
- } catch ( error ) {
- console.error( error );
- }
- };
- //
- this.reset = function () {
- for ( var i = 0; i < enabledAttributes.length; i ++ ) {
- if ( enabledAttributes[ i ] === 1 ) {
- gl.disableVertexAttribArray( i );
- enabledAttributes[ i ] = 0;
- }
- }
- capabilities = {};
- compressedTextureFormats = null;
- currentBlending = null;
- currentDepthWrite = null;
- currentColorWrite = null;
- currentFlipSided = null;
- };
- };
|