123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- import { GLRenderingContext } from './compat';
- export type WebGLState = {
- currentProgramId: number
- currentMaterialId: number
- currentRenderItemId: number
- /**
- * specifies which WebGL capability to enable
- * - `gl.BLEND`: blending of the computed fragment color values
- * - `gl.CULL_FACE`: culling of polygons
- * - `gl.DEPTH_TEST`: depth comparisons and updates to the depth buffer
- * - `gl.DITHER`: dithering of color components before they get written to the color buffer
- * - `gl.POLYGON_OFFSET_FILL`: adding an offset to depth values of polygon's fragments
- * - `gl.SAMPLE_ALPHA_TO_COVERAGE`: computation of a temporary coverage value determined by the alpha value
- * - `gl.SAMPLE_COVERAGE`: ANDing the fragment's coverage with the temporary coverage value
- * - `gl.SCISSOR_TEST`: scissor test that discards fragments that are outside of the scissor rectangle
- * - `gl.STENCIL_TEST`: stencil testing and updates to the stencil buffer
- */
- enable: (cap: number) => void
- /**
- * specifies which WebGL capability to disable
- * - `gl.BLEND`: blending of the computed fragment color values
- * - `gl.CULL_FACE`: culling of polygons
- * - `gl.DEPTH_TEST`: depth comparisons and updates to the depth buffer
- * - `gl.DITHER`: dithering of color components before they get written to the color buffer
- * - `gl.POLYGON_OFFSET_FILL`: adding an offset to depth values of polygon's fragments
- * - `gl.SAMPLE_ALPHA_TO_COVERAGE`: computation of a temporary coverage value determined by the alpha value
- * - `gl.SAMPLE_COVERAGE`: ANDing the fragment's coverage with the temporary coverage value
- * - `gl.SCISSOR_TEST`: scissor test that discards fragments that are outside of the scissor rectangle
- * - `gl.STENCIL_TEST`: stencil testing and updates to the stencil buffer
- */
- disable: (cap: number) => void
- /** specifies whether polygons are front- or back-facing by setting a winding orientation */
- frontFace: (mode: number) => void
- /** specifies whether or not front- and/or back-facing polygons can be culled */
- cullFace: (mode: number) => void
- /** sets whether writing into the depth buffer is enabled or disabled */
- depthMask: (flag: boolean) => void
- /** sets which color components to enable or to disable */
- colorMask: (red: boolean, green: boolean, blue: boolean, alpha: boolean) => void
- /** specifies the color values used when clearing color buffers, used when calling `gl.clear`, clamped to [0, 1] */
- clearColor: (red: number, green: number, blue: number, alpha: number) => void
- /** defines which function is used for blending pixel arithmetic */
- blendFunc: (src: number, dst: number) => void
- /** defines which function is used for blending pixel arithmetic for RGB and alpha components separately */
- blendFuncSeparate: (srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => void
- /** set both the RGB blend equation and alpha blend equation to a single equation, determines how a new pixel is combined with an existing */
- blendEquation: (mode: number) => void
- /** set the RGB blend equation and alpha blend equation separately, determines how a new pixel is combined with an existing */
- blendEquationSeparate: (modeRGB: number, modeAlpha: number) => void
- }
- export function createState(gl: GLRenderingContext): WebGLState {
- const enabledCapabilities: { [k: number]: boolean } = {}
- let currentFrontFace = gl.getParameter(gl.FRONT_FACE)
- let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE)
- let currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK)
- let currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK)
- let currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE)
- let currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB)
- let currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB)
- let currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA)
- let currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA)
- let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB)
- let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA)
- return {
- currentProgramId: -1,
- currentMaterialId: -1,
- currentRenderItemId: -1,
- enable: (cap: number) => {
- if (enabledCapabilities[cap] !== true ) {
- gl.enable(cap)
- enabledCapabilities[cap] = true
- }
- },
- disable: (cap: number) => {
- if (enabledCapabilities[cap] !== false) {
- gl.disable(cap)
- enabledCapabilities[cap] = false
- }
- },
- frontFace: (mode: number) => {
- if (mode !== currentFrontFace) {
- gl.frontFace(mode)
- currentFrontFace = mode
- }
- },
- cullFace: (mode: number) => {
- if (mode !== currentCullFace) {
- gl.cullFace(mode)
- currentCullFace = mode
- }
- },
- depthMask: (flag: boolean) => {
- if (flag !== currentDepthMask) {
- gl.depthMask(flag)
- currentDepthMask = flag
- }
- },
- colorMask: (red: boolean, green: boolean, blue: boolean, alpha: boolean) => {
- if (red !== currentColorMask[0] || green !== currentColorMask[1] || blue !== currentColorMask[2] || alpha !== currentColorMask[3]) {
- gl.colorMask(red, green, blue, alpha)
- currentColorMask[0] = red
- currentColorMask[1] = green
- currentColorMask[2] = blue
- currentColorMask[3] = alpha
- }
- },
- clearColor: (red: number, green: number, blue: number, alpha: number) => {
- if (red !== currentClearColor[0] || green !== currentClearColor[1] || blue !== currentClearColor[2] || alpha !== currentClearColor[3]) {
- gl.clearColor(red, green, blue, alpha)
- currentClearColor[0] = red
- currentClearColor[1] = green
- currentClearColor[2] = blue
- currentClearColor[3] = alpha
- }
- },
- blendFunc: (src: number, dst: number) => {
- if (src !== currentBlendSrcRGB || dst !== currentBlendDstRGB || src !== currentBlendSrcAlpha || dst !== currentBlendDstAlpha) {
- gl.blendFunc(src, dst)
- currentBlendSrcRGB = src
- currentBlendDstRGB = dst
- currentBlendSrcAlpha = src
- currentBlendDstAlpha = dst
- }
- },
- blendFuncSeparate: (srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => {
- if (srcRGB !== currentBlendSrcRGB || dstRGB !== currentBlendDstRGB || srcAlpha !== currentBlendSrcAlpha || dstAlpha !== currentBlendDstAlpha) {
- gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)
- currentBlendSrcRGB = srcRGB
- currentBlendDstRGB = dstRGB
- currentBlendSrcAlpha = srcAlpha
- currentBlendDstAlpha = dstAlpha
- }
- },
- blendEquation: (mode: number) => {
- if (mode !== currentBlendEqRGB || mode !== currentBlendEqAlpha) {
- gl.blendEquation(mode)
- currentBlendEqRGB = mode
- currentBlendEqAlpha = mode
- }
- },
- blendEquationSeparate: (modeRGB: number, modeAlpha: number) => {
- if (modeRGB !== currentBlendEqRGB || modeAlpha !== currentBlendEqAlpha) {
- gl.blendEquationSeparate(modeRGB, modeAlpha)
- currentBlendEqRGB = modeRGB
- currentBlendEqAlpha = modeAlpha
- }
- }
- }
- }
|