|
@@ -6,10 +6,12 @@
|
|
|
|
|
|
import { createProgramCache, ProgramCache } from './program'
|
|
import { createProgramCache, ProgramCache } from './program'
|
|
import { createShaderCache, ShaderCache } from './shader'
|
|
import { createShaderCache, ShaderCache } from './shader'
|
|
-import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, getVertexArrayObject, isWebGL2, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture } from './compat';
|
|
|
|
|
|
+import { GLRenderingContext, isWebGL2 } from './compat';
|
|
import { createFramebufferCache, FramebufferCache, checkFramebufferStatus } from './framebuffer';
|
|
import { createFramebufferCache, FramebufferCache, checkFramebufferStatus } from './framebuffer';
|
|
import { Scheduler } from 'mol-task';
|
|
import { Scheduler } from 'mol-task';
|
|
import { isDebugMode } from 'mol-util/debug';
|
|
import { isDebugMode } from 'mol-util/debug';
|
|
|
|
+import { createExtensions, WebGLExtensions } from './extensions';
|
|
|
|
+import { WebGLState, createState } from './state';
|
|
|
|
|
|
export function getGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes): GLRenderingContext | null {
|
|
export function getGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes): GLRenderingContext | null {
|
|
function getContext(contextId: 'webgl' | 'experimental-webgl' | 'webgl2') {
|
|
function getContext(contextId: 'webgl' | 'experimental-webgl' | 'webgl2') {
|
|
@@ -149,90 +151,6 @@ export function createImageData(buffer: ArrayLike<number>, width: number, height
|
|
|
|
|
|
//
|
|
//
|
|
|
|
|
|
-export type WebGLExtensions = {
|
|
|
|
- instancedArrays: COMPAT_instanced_arrays
|
|
|
|
- standardDerivatives: COMPAT_standard_derivatives
|
|
|
|
- blendMinMax: COMPAT_blend_minmax
|
|
|
|
- textureFloat: COMPAT_texture_float
|
|
|
|
- textureFloatLinear: COMPAT_texture_float_linear
|
|
|
|
- elementIndexUint: COMPAT_element_index_uint
|
|
|
|
- depthTexture: COMPAT_depth_texture
|
|
|
|
-
|
|
|
|
- vertexArrayObject: COMPAT_vertex_array_object | null
|
|
|
|
- fragDepth: COMPAT_frag_depth | null
|
|
|
|
- colorBufferFloat: COMPAT_color_buffer_float | null
|
|
|
|
- drawBuffers: COMPAT_draw_buffers | null
|
|
|
|
- shaderTextureLod: COMPAT_shader_texture_lod | null
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-function createExtensions(gl: GLRenderingContext): WebGLExtensions {
|
|
|
|
- const instancedArrays = getInstancedArrays(gl)
|
|
|
|
- if (instancedArrays === null) {
|
|
|
|
- throw new Error('Could not find support for "instanced_arrays"')
|
|
|
|
- }
|
|
|
|
- const standardDerivatives = getStandardDerivatives(gl)
|
|
|
|
- if (standardDerivatives === null) {
|
|
|
|
- throw new Error('Could not find support for "standard_derivatives"')
|
|
|
|
- }
|
|
|
|
- const blendMinMax = getBlendMinMax(gl)
|
|
|
|
- if (blendMinMax === null) {
|
|
|
|
- throw new Error('Could not find support for "blend_minmax"')
|
|
|
|
- }
|
|
|
|
- const textureFloat = getTextureFloat(gl)
|
|
|
|
- if (textureFloat === null) {
|
|
|
|
- throw new Error('Could not find support for "texture_float"')
|
|
|
|
- }
|
|
|
|
- const textureFloatLinear = getTextureFloatLinear(gl)
|
|
|
|
- if (textureFloatLinear === null) {
|
|
|
|
- throw new Error('Could not find support for "texture_float_linear"')
|
|
|
|
- }
|
|
|
|
- const elementIndexUint = getElementIndexUint(gl)
|
|
|
|
- if (elementIndexUint === null) {
|
|
|
|
- throw new Error('Could not find support for "element_index_uint"')
|
|
|
|
- }
|
|
|
|
- const depthTexture = getDepthTexture(gl)
|
|
|
|
- if (depthTexture === null) {
|
|
|
|
- throw new Error('Could not find support for "depth_texture"')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const vertexArrayObject = getVertexArrayObject(gl)
|
|
|
|
- if (vertexArrayObject === null) {
|
|
|
|
- console.log('Could not find support for "vertex_array_object"')
|
|
|
|
- }
|
|
|
|
- const fragDepth = getFragDepth(gl)
|
|
|
|
- if (fragDepth === null) {
|
|
|
|
- console.log('Could not find support for "frag_depth"')
|
|
|
|
- }
|
|
|
|
- const colorBufferFloat = getColorBufferFloat(gl)
|
|
|
|
- if (colorBufferFloat === null) {
|
|
|
|
- console.log('Could not find support for "color_buffer_float"')
|
|
|
|
- }
|
|
|
|
- const drawBuffers = getDrawBuffers(gl)
|
|
|
|
- if (drawBuffers === null) {
|
|
|
|
- console.log('Could not find support for "draw_buffers"')
|
|
|
|
- }
|
|
|
|
- const shaderTextureLod = getShaderTextureLod(gl)
|
|
|
|
- if (shaderTextureLod === null) {
|
|
|
|
- console.log('Could not find support for "shader_texture_lod"')
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return {
|
|
|
|
- instancedArrays,
|
|
|
|
- standardDerivatives,
|
|
|
|
- blendMinMax,
|
|
|
|
- textureFloat,
|
|
|
|
- textureFloatLinear,
|
|
|
|
- elementIndexUint,
|
|
|
|
- depthTexture,
|
|
|
|
-
|
|
|
|
- vertexArrayObject,
|
|
|
|
- fragDepth,
|
|
|
|
- colorBufferFloat,
|
|
|
|
- drawBuffers,
|
|
|
|
- shaderTextureLod,
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
export type WebGLStats = {
|
|
export type WebGLStats = {
|
|
bufferCount: number
|
|
bufferCount: number
|
|
framebufferCount: number
|
|
framebufferCount: number
|
|
@@ -259,165 +177,7 @@ function createStats(): WebGLStats {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-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
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-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
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
|
|
/** A WebGL context object, including the rendering context, resource caches and counts */
|
|
/** A WebGL context object, including the rendering context, resource caches and counts */
|
|
export interface WebGLContext {
|
|
export interface WebGLContext {
|