Spaces:
Running
Running
| import { | |
| NotEqualDepth, | |
| GreaterDepth, | |
| GreaterEqualDepth, | |
| EqualDepth, | |
| LessEqualDepth, | |
| LessDepth, | |
| AlwaysDepth, | |
| NeverDepth, | |
| CullFaceFront, | |
| CullFaceBack, | |
| CullFaceNone, | |
| DoubleSide, | |
| BackSide, | |
| CustomBlending, | |
| MultiplyBlending, | |
| SubtractiveBlending, | |
| AdditiveBlending, | |
| NoBlending, | |
| NormalBlending, | |
| AddEquation, | |
| SubtractEquation, | |
| ReverseSubtractEquation, | |
| MinEquation, | |
| MaxEquation, | |
| ZeroFactor, | |
| OneFactor, | |
| SrcColorFactor, | |
| SrcAlphaFactor, | |
| SrcAlphaSaturateFactor, | |
| DstColorFactor, | |
| DstAlphaFactor, | |
| OneMinusSrcColorFactor, | |
| OneMinusSrcAlphaFactor, | |
| OneMinusDstColorFactor, | |
| OneMinusDstAlphaFactor, | |
| } from '../../constants.js'; | |
| import { Vector4 } from '../../math/Vector4.js'; | |
| function WebGLState(gl, extensions, capabilities) { | |
| const isWebGL2 = capabilities.isWebGL2; | |
| function ColorBuffer() { | |
| let locked = false; | |
| const color = new Vector4(); | |
| let currentColorMask = null; | |
| const currentColorClear = new Vector4(0, 0, 0, 0); | |
| return { | |
| setMask: function (colorMask) { | |
| if (currentColorMask !== colorMask && !locked) { | |
| gl.colorMask(colorMask, colorMask, colorMask, colorMask); | |
| currentColorMask = colorMask; | |
| } | |
| }, | |
| setLocked: function (lock) { | |
| locked = lock; | |
| }, | |
| 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() { | |
| let locked = false; | |
| let currentDepthMask = null; | |
| let currentDepthFunc = null; | |
| let 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; | |
| } | |
| }, | |
| 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; | |
| }, | |
| setClear: function (depth) { | |
| if (currentDepthClear !== depth) { | |
| gl.clearDepth(depth); | |
| currentDepthClear = depth; | |
| } | |
| }, | |
| reset: function () { | |
| locked = false; | |
| currentDepthMask = null; | |
| currentDepthFunc = null; | |
| currentDepthClear = null; | |
| }, | |
| }; | |
| } | |
| function StencilBuffer() { | |
| let locked = false; | |
| let currentStencilMask = null; | |
| let currentStencilFunc = null; | |
| let currentStencilRef = null; | |
| let currentStencilFuncMask = null; | |
| let currentStencilFail = null; | |
| let currentStencilZFail = null; | |
| let currentStencilZPass = null; | |
| let currentStencilClear = null; | |
| return { | |
| setTest: function (stencilTest) { | |
| if (!locked) { | |
| 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; | |
| } | |
| }, | |
| 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; | |
| }, | |
| }; | |
| } | |
| // | |
| const colorBuffer = new ColorBuffer(); | |
| const depthBuffer = new DepthBuffer(); | |
| const stencilBuffer = new StencilBuffer(); | |
| let enabledCapabilities = {}; | |
| let currentBoundFramebuffers = {}; | |
| let currentDrawbuffers = new WeakMap(); | |
| let defaultDrawbuffers = []; | |
| let currentProgram = null; | |
| let currentBlendingEnabled = false; | |
| let currentBlending = null; | |
| let currentBlendEquation = null; | |
| let currentBlendSrc = null; | |
| let currentBlendDst = null; | |
| let currentBlendEquationAlpha = null; | |
| let currentBlendSrcAlpha = null; | |
| let currentBlendDstAlpha = null; | |
| let currentPremultipledAlpha = false; | |
| let currentFlipSided = null; | |
| let currentCullFace = null; | |
| let currentLineWidth = null; | |
| let currentPolygonOffsetFactor = null; | |
| let currentPolygonOffsetUnits = null; | |
| const maxTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); | |
| let lineWidthAvailable = false; | |
| let version = 0; | |
| const glVersion = gl.getParameter(gl.VERSION); | |
| if (glVersion.indexOf('WebGL') !== -1) { | |
| version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]); | |
| lineWidthAvailable = version >= 1.0; | |
| } else if (glVersion.indexOf('OpenGL ES') !== -1) { | |
| version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]); | |
| lineWidthAvailable = version >= 2.0; | |
| } | |
| let currentTextureSlot = null; | |
| let currentBoundTextures = {}; | |
| const scissorParam = gl.getParameter(gl.SCISSOR_BOX); | |
| const viewportParam = gl.getParameter(gl.VIEWPORT); | |
| const currentScissor = new Vector4().fromArray(scissorParam); | |
| const currentViewport = new Vector4().fromArray(viewportParam); | |
| function createTexture(type, target, count) { | |
| const data = new Uint8Array(4); // 4 is required to match default unpack alignment of 4. | |
| const texture = gl.createTexture(); | |
| gl.bindTexture(type, texture); | |
| gl.texParameteri(type, gl.TEXTURE_MIN_FILTER, gl.NEAREST); | |
| gl.texParameteri(type, gl.TEXTURE_MAG_FILTER, gl.NEAREST); | |
| for (let i = 0; i < count; i++) { | |
| gl.texImage2D(target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); | |
| } | |
| return texture; | |
| } | |
| const emptyTextures = {}; | |
| emptyTextures[gl.TEXTURE_2D] = createTexture(gl.TEXTURE_2D, gl.TEXTURE_2D, 1); | |
| 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); | |
| setFlipSided(false); | |
| setCullFace(CullFaceBack); | |
| enable(gl.CULL_FACE); | |
| setBlending(NoBlending); | |
| // | |
| function enable(id) { | |
| if (enabledCapabilities[id] !== true) { | |
| gl.enable(id); | |
| enabledCapabilities[id] = true; | |
| } | |
| } | |
| function disable(id) { | |
| if (enabledCapabilities[id] !== false) { | |
| gl.disable(id); | |
| enabledCapabilities[id] = false; | |
| } | |
| } | |
| function bindFramebuffer(target, framebuffer) { | |
| if (currentBoundFramebuffers[target] !== framebuffer) { | |
| gl.bindFramebuffer(target, framebuffer); | |
| currentBoundFramebuffers[target] = framebuffer; | |
| if (isWebGL2) { | |
| // 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; | |
| } | |
| function drawBuffers(renderTarget, framebuffer) { | |
| let drawBuffers = defaultDrawbuffers; | |
| let needsUpdate = false; | |
| if (renderTarget) { | |
| drawBuffers = currentDrawbuffers.get(framebuffer); | |
| if (drawBuffers === undefined) { | |
| drawBuffers = []; | |
| currentDrawbuffers.set(framebuffer, drawBuffers); | |
| } | |
| if (renderTarget.isWebGLMultipleRenderTargets) { | |
| const textures = renderTarget.texture; | |
| 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.COLOR_ATTACHMENT0) { | |
| drawBuffers[0] = gl.COLOR_ATTACHMENT0; | |
| needsUpdate = true; | |
| } | |
| } | |
| } else { | |
| if (drawBuffers[0] !== gl.BACK) { | |
| drawBuffers[0] = gl.BACK; | |
| needsUpdate = true; | |
| } | |
| } | |
| if (needsUpdate) { | |
| if (capabilities.isWebGL2) { | |
| gl.drawBuffers(drawBuffers); | |
| } else { | |
| extensions.get('WEBGL_draw_buffers').drawBuffersWEBGL(drawBuffers); | |
| } | |
| } | |
| } | |
| function useProgram(program) { | |
| if (currentProgram !== program) { | |
| gl.useProgram(program); | |
| currentProgram = program; | |
| return true; | |
| } | |
| return false; | |
| } | |
| const equationToGL = { | |
| [AddEquation]: gl.FUNC_ADD, | |
| [SubtractEquation]: gl.FUNC_SUBTRACT, | |
| [ReverseSubtractEquation]: gl.FUNC_REVERSE_SUBTRACT, | |
| }; | |
| if (isWebGL2) { | |
| equationToGL[MinEquation] = gl.MIN; | |
| equationToGL[MaxEquation] = gl.MAX; | |
| } else { | |
| const extension = extensions.get('EXT_blend_minmax'); | |
| if (extension !== null) { | |
| equationToGL[MinEquation] = extension.MIN_EXT; | |
| equationToGL[MaxEquation] = extension.MAX_EXT; | |
| } | |
| } | |
| const 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, | |
| }; | |
| function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) { | |
| if (blending === NoBlending) { | |
| if (currentBlendingEnabled === true) { | |
| disable(gl.BLEND); | |
| currentBlendingEnabled = false; | |
| } | |
| return; | |
| } | |
| if (currentBlendingEnabled === false) { | |
| enable(gl.BLEND); | |
| currentBlendingEnabled = true; | |
| } | |
| if (blending !== CustomBlending) { | |
| if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) { | |
| if (currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation) { | |
| gl.blendEquation(gl.FUNC_ADD); | |
| currentBlendEquation = AddEquation; | |
| 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.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA); | |
| 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.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR); | |
| break; | |
| case MultiplyBlending: | |
| gl.blendFunc(gl.ZERO, gl.SRC_COLOR); | |
| break; | |
| default: | |
| console.error('THREE.WebGLState: Invalid blending: ', blending); | |
| break; | |
| } | |
| } | |
| currentBlendSrc = null; | |
| currentBlendDst = null; | |
| currentBlendSrcAlpha = null; | |
| currentBlendDstAlpha = null; | |
| currentBlending = blending; | |
| currentPremultipledAlpha = premultipliedAlpha; | |
| } | |
| return; | |
| } | |
| // custom blending | |
| blendEquationAlpha = blendEquationAlpha || blendEquation; | |
| blendSrcAlpha = blendSrcAlpha || blendSrc; | |
| blendDstAlpha = blendDstAlpha || blendDst; | |
| if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) { | |
| gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]); | |
| currentBlendEquation = blendEquation; | |
| currentBlendEquationAlpha = blendEquationAlpha; | |
| } | |
| if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) { | |
| gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]); | |
| currentBlendSrc = blendSrc; | |
| currentBlendDst = blendDst; | |
| currentBlendSrcAlpha = blendSrcAlpha; | |
| currentBlendDstAlpha = blendDstAlpha; | |
| } | |
| currentBlending = blending; | |
| currentPremultipledAlpha = null; | |
| } | |
| function setMaterial(material, frontFaceCW) { | |
| material.side === DoubleSide ? disable(gl.CULL_FACE) : enable(gl.CULL_FACE); | |
| let 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); | |
| const stencilWrite = material.stencilWrite; | |
| stencilBuffer.setTest(stencilWrite); | |
| if (stencilWrite) { | |
| stencilBuffer.setMask(material.stencilWriteMask); | |
| stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask); | |
| stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass); | |
| } | |
| setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits); | |
| material.alphaToCoverage === true ? enable(gl.SAMPLE_ALPHA_TO_COVERAGE) : disable(gl.SAMPLE_ALPHA_TO_COVERAGE); | |
| } | |
| // | |
| function setFlipSided(flipSided) { | |
| if (currentFlipSided !== flipSided) { | |
| if (flipSided) { | |
| gl.frontFace(gl.CW); | |
| } else { | |
| gl.frontFace(gl.CCW); | |
| } | |
| currentFlipSided = flipSided; | |
| } | |
| } | |
| 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; | |
| } | |
| function setLineWidth(width) { | |
| if (width !== currentLineWidth) { | |
| if (lineWidthAvailable) gl.lineWidth(width); | |
| currentLineWidth = width; | |
| } | |
| } | |
| function setPolygonOffset(polygonOffset, factor, units) { | |
| if (polygonOffset) { | |
| enable(gl.POLYGON_OFFSET_FILL); | |
| if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) { | |
| gl.polygonOffset(factor, units); | |
| currentPolygonOffsetFactor = factor; | |
| currentPolygonOffsetUnits = units; | |
| } | |
| } else { | |
| disable(gl.POLYGON_OFFSET_FILL); | |
| } | |
| } | |
| function setScissorTest(scissorTest) { | |
| if (scissorTest) { | |
| enable(gl.SCISSOR_TEST); | |
| } else { | |
| disable(gl.SCISSOR_TEST); | |
| } | |
| } | |
| // texture | |
| function activeTexture(webglSlot) { | |
| if (webglSlot === undefined) webglSlot = gl.TEXTURE0 + maxTextures - 1; | |
| if (currentTextureSlot !== webglSlot) { | |
| gl.activeTexture(webglSlot); | |
| currentTextureSlot = webglSlot; | |
| } | |
| } | |
| function bindTexture(webglType, webglTexture) { | |
| if (currentTextureSlot === null) { | |
| activeTexture(); | |
| } | |
| let 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 || emptyTextures[webglType]); | |
| boundTexture.type = webglType; | |
| boundTexture.texture = webglTexture; | |
| } | |
| } | |
| function unbindTexture() { | |
| const boundTexture = currentBoundTextures[currentTextureSlot]; | |
| if (boundTexture !== undefined && boundTexture.type !== undefined) { | |
| gl.bindTexture(boundTexture.type, null); | |
| boundTexture.type = undefined; | |
| boundTexture.texture = undefined; | |
| } | |
| } | |
| function compressedTexImage2D() { | |
| try { | |
| gl.compressedTexImage2D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texSubImage2D() { | |
| try { | |
| gl.texSubImage2D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texSubImage3D() { | |
| try { | |
| gl.texSubImage3D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function compressedTexSubImage2D() { | |
| try { | |
| gl.compressedTexSubImage2D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texStorage2D() { | |
| try { | |
| gl.texStorage2D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texStorage3D() { | |
| try { | |
| gl.texStorage3D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texImage2D() { | |
| try { | |
| gl.texImage2D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| function texImage3D() { | |
| try { | |
| gl.texImage3D.apply(gl, arguments); | |
| } catch (error) { | |
| console.error('THREE.WebGLState:', error); | |
| } | |
| } | |
| // | |
| function scissor(scissor) { | |
| if (currentScissor.equals(scissor) === false) { | |
| gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w); | |
| currentScissor.copy(scissor); | |
| } | |
| } | |
| function viewport(viewport) { | |
| if (currentViewport.equals(viewport) === false) { | |
| gl.viewport(viewport.x, viewport.y, viewport.z, viewport.w); | |
| currentViewport.copy(viewport); | |
| } | |
| } | |
| // | |
| function reset() { | |
| // reset state | |
| gl.disable(gl.BLEND); | |
| gl.disable(gl.CULL_FACE); | |
| gl.disable(gl.DEPTH_TEST); | |
| gl.disable(gl.POLYGON_OFFSET_FILL); | |
| gl.disable(gl.SCISSOR_TEST); | |
| gl.disable(gl.STENCIL_TEST); | |
| gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE); | |
| gl.blendEquation(gl.FUNC_ADD); | |
| gl.blendFunc(gl.ONE, gl.ZERO); | |
| gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO); | |
| gl.colorMask(true, true, true, true); | |
| gl.clearColor(0, 0, 0, 0); | |
| gl.depthMask(true); | |
| gl.depthFunc(gl.LESS); | |
| gl.clearDepth(1); | |
| gl.stencilMask(0xffffffff); | |
| gl.stencilFunc(gl.ALWAYS, 0, 0xffffffff); | |
| gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); | |
| gl.clearStencil(0); | |
| gl.cullFace(gl.BACK); | |
| gl.frontFace(gl.CCW); | |
| gl.polygonOffset(0, 0); | |
| gl.activeTexture(gl.TEXTURE0); | |
| gl.bindFramebuffer(gl.FRAMEBUFFER, null); | |
| if (isWebGL2 === true) { | |
| gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); | |
| gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); | |
| } | |
| gl.useProgram(null); | |
| gl.lineWidth(1); | |
| gl.scissor(0, 0, gl.canvas.width, gl.canvas.height); | |
| gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); | |
| // reset internals | |
| enabledCapabilities = {}; | |
| currentTextureSlot = null; | |
| currentBoundTextures = {}; | |
| currentBoundFramebuffers = {}; | |
| currentDrawbuffers = new WeakMap(); | |
| defaultDrawbuffers = []; | |
| currentProgram = null; | |
| currentBlendingEnabled = false; | |
| currentBlending = null; | |
| currentBlendEquation = null; | |
| currentBlendSrc = null; | |
| currentBlendDst = null; | |
| currentBlendEquationAlpha = null; | |
| currentBlendSrcAlpha = null; | |
| currentBlendDstAlpha = null; | |
| currentPremultipledAlpha = false; | |
| currentFlipSided = null; | |
| currentCullFace = null; | |
| currentLineWidth = null; | |
| currentPolygonOffsetFactor = null; | |
| currentPolygonOffsetUnits = null; | |
| currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height); | |
| currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height); | |
| colorBuffer.reset(); | |
| depthBuffer.reset(); | |
| stencilBuffer.reset(); | |
| } | |
| return { | |
| buffers: { | |
| color: colorBuffer, | |
| depth: depthBuffer, | |
| stencil: stencilBuffer, | |
| }, | |
| enable: enable, | |
| disable: disable, | |
| bindFramebuffer: bindFramebuffer, | |
| drawBuffers: drawBuffers, | |
| useProgram: useProgram, | |
| setBlending: setBlending, | |
| setMaterial: setMaterial, | |
| setFlipSided: setFlipSided, | |
| setCullFace: setCullFace, | |
| setLineWidth: setLineWidth, | |
| setPolygonOffset: setPolygonOffset, | |
| setScissorTest: setScissorTest, | |
| activeTexture: activeTexture, | |
| bindTexture: bindTexture, | |
| unbindTexture: unbindTexture, | |
| compressedTexImage2D: compressedTexImage2D, | |
| texImage2D: texImage2D, | |
| texImage3D: texImage3D, | |
| texStorage2D: texStorage2D, | |
| texStorage3D: texStorage3D, | |
| texSubImage2D: texSubImage2D, | |
| texSubImage3D: texSubImage3D, | |
| compressedTexSubImage2D: compressedTexSubImage2D, | |
| scissor: scissor, | |
| viewport: viewport, | |
| reset: reset, | |
| }; | |
| } | |
| export { WebGLState }; | |