123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- import {
- CullFaceNone, CullFaceBack, CullFaceFront, DoubleSide, BackSide,
- NormalBlending, NoBlending, CustomBlending, AddEquation,
- AdditiveBlending, SubtractiveBlending, MultiplyBlending, SubtractEquation, ReverseSubtractEquation,
- ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor,
- OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor,
- NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, EqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth
- } from 'three';
- let initialized = false, equationToGL, factorToGL;
- class WebGLState {
- constructor( backend ) {
- this.backend = backend;
- this.gl = this.backend.gl;
- this.enabled = {};
- this.currentFlipSided = null;
- this.currentCullFace = null;
- this.currentProgram = null;
- this.currentBlendingEnabled = false;
- this.currentBlending = null;
- this.currentBlendSrc = null;
- this.currentBlendDst = null;
- this.currentBlendSrcAlpha = null;
- this.currentBlendDstAlpha = null;
- this.currentPremultipledAlpha = null;
- this.currentPolygonOffsetFactor = null;
- this.currentPolygonOffsetUnits = null;
- this.currentColorMask = null;
- this.currentDepthFunc = null;
- this.currentDepthMask = null;
- this.currentStencilFunc = null;
- this.currentStencilRef = null;
- this.currentStencilFuncMask = null;
- this.currentStencilFail = null;
- this.currentStencilZFail = null;
- this.currentStencilZPass = null;
- this.currentStencilMask = null;
- if ( initialized === false ) {
- this._init( this.gl );
- initialized = true;
- }
- }
- _init( gl ) {
- // Store only WebGL constants here.
- equationToGL = {
- [ AddEquation ]: gl.FUNC_ADD,
- [ SubtractEquation ]: gl.FUNC_SUBTRACT,
- [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT
- };
- factorToGL = {
- [ ZeroFactor ]: gl.ZERO,
- [ OneFactor ]: gl.ONE,
- [ SrcColorFactor ]: gl.SRC_COLOR,
- [ SrcAlphaFactor ]: gl.SRC_ALPHA,
- [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE,
- [ DstColorFactor ]: gl.DST_COLOR,
- [ DstAlphaFactor ]: gl.DST_ALPHA,
- [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR,
- [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA,
- [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR,
- [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA
- };
- }
- enable( id ) {
- const { enabled } = this;
- if ( enabled[ id ] !== true ) {
- this.gl.enable( id );
- enabled[ id ] = true;
- }
- }
- disable( id ) {
- const { enabled } = this;
- if ( enabled[ id ] !== false ) {
- this.gl.disable( id );
- enabled[ id ] = false;
- }
- }
- setFlipSided( flipSided ) {
- if ( this.currentFlipSided !== flipSided ) {
- const { gl } = this;
- if ( flipSided ) {
- gl.frontFace( gl.CW );
- } else {
- gl.frontFace( gl.CCW );
- }
- this.currentFlipSided = flipSided;
- }
- }
- setCullFace( cullFace ) {
- const { gl } = this;
- if ( cullFace !== CullFaceNone ) {
- this.enable( gl.CULL_FACE );
- if ( cullFace !== this.currentCullFace ) {
- if ( cullFace === CullFaceBack ) {
- gl.cullFace( gl.BACK );
- } else if ( cullFace === CullFaceFront ) {
- gl.cullFace( gl.FRONT );
- } else {
- gl.cullFace( gl.FRONT_AND_BACK );
- }
- }
- } else {
- this.disable( gl.CULL_FACE );
- }
- this.currentCullFace = cullFace;
- }
- setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
- const { gl } = this;
- if ( blending === NoBlending ) {
- if ( this.currentBlendingEnabled === true ) {
- this.disable( gl.BLEND );
- this.currentBlendingEnabled = false;
- }
- return;
- }
- if ( this.currentBlendingEnabled === false ) {
- this.enable( gl.BLEND );
- this.currentBlendingEnabled = true;
- }
- if ( blending !== CustomBlending ) {
- if ( blending !== this.currentBlending || premultipliedAlpha !== this.currentPremultipledAlpha ) {
- if ( this.currentBlendEquation !== AddEquation || this.currentBlendEquationAlpha !== AddEquation ) {
- gl.blendEquation( gl.FUNC_ADD );
- this.currentBlendEquation = AddEquation;
- this.currentBlendEquationAlpha = AddEquation;
- }
- if ( premultipliedAlpha ) {
- switch ( blending ) {
- case NormalBlending:
- gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
- break;
- case AdditiveBlending:
- gl.blendFunc( gl.ONE, gl.ONE );
- break;
- case SubtractiveBlending:
- gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
- break;
- case MultiplyBlending:
- gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
- break;
- default:
- console.error( 'THREE.WebGLState: Invalid blending: ', blending );
- break;
- }
- } else {
- switch ( blending ) {
- case NormalBlending:
- gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
- break;
- case AdditiveBlending:
- gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
- break;
- case SubtractiveBlending:
- gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
- break;
- case MultiplyBlending:
- gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
- break;
- default:
- console.error( 'THREE.WebGLState: Invalid blending: ', blending );
- break;
- }
- }
- this.currentBlendSrc = null;
- this.currentBlendDst = null;
- this.currentBlendSrcAlpha = null;
- this.currentBlendDstAlpha = null;
- this.currentBlending = blending;
- this.currentPremultipledAlpha = premultipliedAlpha;
- }
- return;
- }
- // custom blending
- blendEquationAlpha = blendEquationAlpha || blendEquation;
- blendSrcAlpha = blendSrcAlpha || blendSrc;
- blendDstAlpha = blendDstAlpha || blendDst;
- if ( blendEquation !== this.currentBlendEquation || blendEquationAlpha !== this.currentBlendEquationAlpha ) {
- gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
- this.currentBlendEquation = blendEquation;
- this.currentBlendEquationAlpha = blendEquationAlpha;
- }
- if ( blendSrc !== this.currentBlendSrc || blendDst !== this.currentBlendDst || blendSrcAlpha !== this.currentBlendSrcAlpha || blendDstAlpha !== this.currentBlendDstAlpha ) {
- gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
- this.currentBlendSrc = blendSrc;
- this.currentBlendDst = blendDst;
- this.currentBlendSrcAlpha = blendSrcAlpha;
- this.currentBlendDstAlpha = blendDstAlpha;
- }
- this.currentBlending = blending;
- this.currentPremultipledAlpha = false;
- }
- setColorMask( colorMask ) {
- if ( this.currentColorMask !== colorMask ) {
- this.gl.colorMask( colorMask, colorMask, colorMask, colorMask );
- this.currentColorMask = colorMask;
- }
- }
- setDepthTest( depthTest ) {
- const { gl } = this;
- if ( depthTest ) {
- this.enable( gl.DEPTH_TEST );
- } else {
- this.disable( gl.DEPTH_TEST );
- }
- }
- setDepthMask( depthMask ) {
- if ( this.currentDepthMask !== depthMask ) {
- this.gl.depthMask( depthMask );
- this.currentDepthMask = depthMask;
- }
- }
- setDepthFunc( depthFunc ) {
- if ( this.currentDepthFunc !== depthFunc ) {
- const { gl } = this;
- 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 );
- }
- this.currentDepthFunc = depthFunc;
- }
- }
- setStencilTest( stencilTest ) {
- const { gl } = this;
- if ( stencilTest ) {
- this.enable( gl.STENCIL_TEST );
- } else {
- this.disable( gl.STENCIL_TEST );
- }
- }
- setStencilMask( stencilMask ) {
- if ( this.currentStencilMask !== stencilMask ) {
- this.gl.stencilMask( stencilMask );
- this.currentStencilMask = stencilMask;
- }
- }
- setStencilFunc( stencilFunc, stencilRef, stencilMask ) {
- if ( this.currentStencilFunc !== stencilFunc ||
- this.currentStencilRef !== stencilRef ||
- this.currentStencilFuncMask !== stencilMask ) {
- this.gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
- this.currentStencilFunc = stencilFunc;
- this.currentStencilRef = stencilRef;
- this.currentStencilFuncMask = stencilMask;
- }
- }
- setStencilOp( stencilFail, stencilZFail, stencilZPass ) {
- if ( this.currentStencilFail !== stencilFail ||
- this.currentStencilZFail !== stencilZFail ||
- this.currentStencilZPass !== stencilZPass ) {
- this.gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
- this.currentStencilFail = stencilFail;
- this.currentStencilZFail = stencilZFail;
- this.currentStencilZPass = stencilZPass;
- }
- }
- setMaterial( material, frontFaceCW ) {
- const { gl } = this;
- material.side === DoubleSide
- ? this.disable( gl.CULL_FACE )
- : this.enable( gl.CULL_FACE );
- let flipSided = ( material.side === BackSide );
- if ( frontFaceCW ) flipSided = ! flipSided;
- this.setFlipSided( flipSided );
- ( material.blending === NormalBlending && material.transparent === false )
- ? this.setBlending( NoBlending )
- : this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
- this.setDepthFunc( material.depthFunc );
- this.setDepthTest( material.depthTest );
- this.setDepthMask( material.depthWrite );
- this.setColorMask( material.colorWrite );
- const stencilWrite = material.stencilWrite;
- this.setStencilTest( stencilWrite );
- if ( stencilWrite ) {
- this.setStencilMask( material.stencilWriteMask );
- this.setStencilFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
- this.setStencilOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
- }
- this.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
- material.alphaToCoverage === true
- ? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
- : this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
- }
- setPolygonOffset( polygonOffset, factor, units ) {
- const { gl } = this;
- if ( polygonOffset ) {
- this.enable( gl.POLYGON_OFFSET_FILL );
- if ( this.currentPolygonOffsetFactor !== factor || this.currentPolygonOffsetUnits !== units ) {
- gl.polygonOffset( factor, units );
- this.currentPolygonOffsetFactor = factor;
- this.currentPolygonOffsetUnits = units;
- }
- } else {
- this.disable( gl.POLYGON_OFFSET_FILL );
- }
- }
- useProgram( program ) {
- if ( this.currentProgram !== program ) {
- this.gl.useProgram( program );
- this.currentProgram = program;
- return true;
- }
- return false;
- }
- }
- export default WebGLState;
|