739 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			739 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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;
 | |
| 		this.currentLineWidth = null;
 | |
| 
 | |
| 		this.currentBoundFramebuffers = {};
 | |
| 		this.currentDrawbuffers = new WeakMap();
 | |
| 
 | |
| 		this.maxTextures = this.gl.getParameter( this.gl.MAX_TEXTURE_IMAGE_UNITS );
 | |
| 		this.currentTextureSlot = null;
 | |
| 		this.currentBoundTextures = {};
 | |
| 
 | |
| 		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;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	setLineWidth( width ) {
 | |
| 
 | |
| 		const { currentLineWidth, gl } = this;
 | |
| 
 | |
| 		if ( width !== currentLineWidth ) {
 | |
| 
 | |
| 			gl.lineWidth( width );
 | |
| 
 | |
| 			this.currentLineWidth = width;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	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;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	// framebuffer
 | |
| 
 | |
| 
 | |
| 	bindFramebuffer( target, framebuffer ) {
 | |
| 
 | |
| 		const { gl, currentBoundFramebuffers } = this;
 | |
| 
 | |
| 		if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
 | |
| 
 | |
| 			gl.bindFramebuffer( target, framebuffer );
 | |
| 
 | |
| 			currentBoundFramebuffers[ target ] = framebuffer;
 | |
| 
 | |
| 			// gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER
 | |
| 
 | |
| 			if ( target === gl.DRAW_FRAMEBUFFER ) {
 | |
| 
 | |
| 				currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			if ( target === gl.FRAMEBUFFER ) {
 | |
| 
 | |
| 				currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			return true;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	drawBuffers( renderContext, framebuffer ) {
 | |
| 
 | |
| 		const { gl } = this;
 | |
| 
 | |
| 		let drawBuffers = [];
 | |
| 
 | |
| 		let needsUpdate = false;
 | |
| 
 | |
| 		if ( renderContext.textures !== null ) {
 | |
| 
 | |
| 			drawBuffers = this.currentDrawbuffers.get( framebuffer );
 | |
| 
 | |
| 			if ( drawBuffers === undefined ) {
 | |
| 
 | |
| 				drawBuffers = [];
 | |
| 				this.currentDrawbuffers.set( framebuffer, drawBuffers );
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 
 | |
| 			const textures = renderContext.textures;
 | |
| 
 | |
| 			if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) {
 | |
| 
 | |
| 				for ( let i = 0, il = textures.length; i < il; i ++ ) {
 | |
| 
 | |
| 					drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i;
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				drawBuffers.length = textures.length;
 | |
| 
 | |
| 				needsUpdate = true;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 
 | |
| 		} else {
 | |
| 
 | |
| 			if ( drawBuffers[ 0 ] !== gl.BACK ) {
 | |
| 
 | |
| 				drawBuffers[ 0 ] = gl.BACK;
 | |
| 
 | |
| 				needsUpdate = true;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( needsUpdate ) {
 | |
| 
 | |
| 			gl.drawBuffers( drawBuffers );
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	// texture
 | |
| 
 | |
| 	activeTexture( webglSlot ) {
 | |
| 
 | |
| 		const { gl, currentTextureSlot, maxTextures } = this;
 | |
| 
 | |
| 		if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
 | |
| 
 | |
| 		if ( currentTextureSlot !== webglSlot ) {
 | |
| 
 | |
| 			gl.activeTexture( webglSlot );
 | |
| 			this.currentTextureSlot = webglSlot;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	bindTexture( webglType, webglTexture, webglSlot ) {
 | |
| 
 | |
| 		const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this;
 | |
| 
 | |
| 		if ( webglSlot === undefined ) {
 | |
| 
 | |
| 			if ( currentTextureSlot === null ) {
 | |
| 
 | |
| 				webglSlot = gl.TEXTURE0 + maxTextures - 1;
 | |
| 
 | |
| 			} else {
 | |
| 
 | |
| 				webglSlot = currentTextureSlot;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		let boundTexture = currentBoundTextures[ webglSlot ];
 | |
| 
 | |
| 		if ( boundTexture === undefined ) {
 | |
| 
 | |
| 			boundTexture = { type: undefined, texture: undefined };
 | |
| 			currentBoundTextures[ webglSlot ] = boundTexture;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
 | |
| 
 | |
| 			if ( currentTextureSlot !== webglSlot ) {
 | |
| 
 | |
| 				gl.activeTexture( webglSlot );
 | |
| 				this.currentTextureSlot = webglSlot;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			gl.bindTexture( webglType, webglTexture );
 | |
| 
 | |
| 			boundTexture.type = webglType;
 | |
| 			boundTexture.texture = webglTexture;
 | |
| 
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	unbindTexture() {
 | |
| 
 | |
| 		const { gl, currentTextureSlot, currentBoundTextures } = this;
 | |
| 
 | |
| 		const boundTexture = currentBoundTextures[ currentTextureSlot ];
 | |
| 
 | |
| 		if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
 | |
| 
 | |
| 			gl.bindTexture( boundTexture.type, null );
 | |
| 
 | |
| 			boundTexture.type = undefined;
 | |
| 			boundTexture.texture = undefined;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| export default WebGLState;
 |