From 6d3bae4e9a9027306a3ac953a1c79cbe899b5d95 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Sun, 7 Oct 2018 11:31:04 -0700 Subject: [PATCH] wip, webgl/webgl2 compatibility layer --- package-lock.json | Bin 412438 -> 412710 bytes package.json | 1 + src/mol-gl/webgl/buffer.ts | 18 +++--- src/mol-gl/webgl/compat.ts | 95 +++++++++++++++++++++++++++++++ src/mol-gl/webgl/context.ts | 64 +++++++++++++-------- src/mol-gl/webgl/render-item.ts | 12 ++-- src/mol-gl/webgl/texture.ts | 2 +- src/mol-gl/webgl/uniform.ts | 10 ++-- src/mol-gl/webgl/vertex-array.ts | 20 +++---- src/mol-view/viewer.ts | 15 +---- tsconfig.json | 5 +- 11 files changed, 173 insertions(+), 69 deletions(-) create mode 100644 src/mol-gl/webgl/compat.ts diff --git a/package-lock.json b/package-lock.json index bd16400a15c501dd7f677b77c573da1d66053668..eef02eb8afb9f6be4baa39aacd2c15fb8fc6b413 100644 GIT binary patch delta 397 zcmbO>O>)@`$qmm`C-+IPv6ZJLrRNw;4~%A(o_=H(lhNe=QtW~dL493)2t(Ik`a>gD zrD-zEtPzgRC59C#u0>u+zM=l1<*C6%NnyU`>A{|nxrSvSdCB2M8E$6&#rm$P;hAP3 z5s{9Oz5xZ=7G-8dRUWyO1+J#)9z_+26;XZ>>Au-sVV)^b1s>(Lwn~%F8^}zuXWRTs zHC=u3hggZt6}}O!lLfX*OnxwhXY=Pt_n2Uu$+FWVH}g&_HU<mWpXJ)T@MJR^oa1_- z8_e1K{My~H=?R*Q64U4DGqP`gq|3OJ5zOB{PoHtC$@B|}jFRoyDU9veDNNh5Q<$fe zPj`68EVEte4)e-3kV47rx06_2n@@M}XOi50Zx+ixjmZIx65Br?X4xDtSz(Xm_6LS+ zY0TSQBv`Er!HTBeo5j+%UA2pK`vRDJI`j5wJvLot7~e>E;sNpLKSkO2x0}1N-Dd>= DJA#*C delta 280 zcmZ2BLvq?Q$qmm`Cr>cooBY6<ZSxPcboJ>x9;{-U%lsl;!K}&mr}A$8Joz3IoHto+ zy5wfQ>BYtn5r=c!n-`yIW<&5iE_OqBn_peO7X}vJeqWDqEhCsY{k|R}$M)3*jO$Fm z{Pu!W#`c0#rtJl(%+t!jLet|PF|%%0y34$>4Z{Da%&4)QD~08#Ify@T`h#CAV%y8- zu;goi_+s1t9%0!M0A_B}Ve4St9w5nTT?pb&oLsP9bh}YE>-Gg8uGlsmwrvo%ZPQ`v ZWZoWT#&((?EHnM|G8Vq=Zf<N3SOI-pWPAVs diff --git a/package.json b/package.json index 71b37e579..33864e84f 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@types/node-fetch": "^2.1.2", "@types/react": "^16.4.14", "@types/react-dom": "^16.0.8", + "@types/webgl2": "0.0.4", "benchmark": "^2.1.4", "cpx": "^1.5.0", "css-loader": "^1.0.0", diff --git a/src/mol-gl/webgl/buffer.ts b/src/mol-gl/webgl/buffer.ts index bde6066f1..8cd11ef8c 100644 --- a/src/mol-gl/webgl/buffer.ts +++ b/src/mol-gl/webgl/buffer.ts @@ -113,8 +113,8 @@ export function createBuffer(ctx: Context, array: ArrayType, itemSize: BufferIte const _itemCount = Math.floor(_length / itemSize) function updateData(array: ArrayType) { - gl.bindBuffer(_bufferType, _buffer) - gl.bufferData(_bufferType, array, _usageHint) + gl.bindBuffer(_bufferType, _buffer); + (gl as WebGLRenderingContext).bufferData(_bufferType, array, _usageHint) // TODO remove cast when webgl2 types are fixed } updateData(array) @@ -136,15 +136,15 @@ export function createBuffer(ctx: Context, array: ArrayType, itemSize: BufferIte updateData, updateSubData: (array: ArrayType, offset: number, count: number) => { - gl.bindBuffer(_bufferType, _buffer) - gl.bufferSubData(_bufferType, offset * _bpe, array.subarray(offset, offset + count)) + gl.bindBuffer(_bufferType, _buffer); + (gl as WebGLRenderingContext).bufferSubData(_bufferType, offset * _bpe, array.subarray(offset, offset + count)) // TODO remove cast when webgl2 types are fixed }, destroy: () => { if (destroyed) return - gl.bindBuffer(_bufferType, _buffer) + gl.bindBuffer(_bufferType, _buffer); // set size to 1 before deleting - gl.bufferData(_bufferType, 1, _usageHint) + (gl as WebGLRenderingContext).bufferData(_bufferType, 1, _usageHint) // TODO remove cast when webgl2 types are fixed gl.deleteBuffer(_buffer) destroyed = true ctx.bufferCount -= 1 @@ -164,7 +164,7 @@ export interface AttributeBuffer extends Buffer { export function createAttributeBuffer<T extends ArrayType, S extends BufferItemSize>(ctx: Context, array: ArrayType, itemSize: S, divisor: number, usageHint: UsageHint = 'dynamic'): AttributeBuffer { const { gl } = ctx - const { angleInstancedArrays } = ctx.extensions + const { instancedArrays } = ctx.extensions const buffer = createBuffer(ctx, array, itemSize, usageHint, 'attribute') const { _buffer, _bufferType, _dataType, _bpe } = buffer @@ -177,12 +177,12 @@ export function createAttributeBuffer<T extends ArrayType, S extends BufferItemS for (let i = 0; i < 4; ++i) { gl.enableVertexAttribArray(location + i) gl.vertexAttribPointer(location + i, 4, _dataType, false, 4 * 4 * _bpe, i * 4 * _bpe) - angleInstancedArrays.vertexAttribDivisorANGLE(location + i, divisor) + instancedArrays.vertexAttribDivisor(location + i, divisor) } } else { gl.enableVertexAttribArray(location) gl.vertexAttribPointer(location, itemSize, _dataType, false, 0, 0) - angleInstancedArrays.vertexAttribDivisorANGLE(location, divisor) + instancedArrays.vertexAttribDivisor(location, divisor) } } } diff --git a/src/mol-gl/webgl/compat.ts b/src/mol-gl/webgl/compat.ts new file mode 100644 index 000000000..2ff0e6bb6 --- /dev/null +++ b/src/mol-gl/webgl/compat.ts @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +export type GLRenderingContext = WebGLRenderingContext | WebGL2RenderingContext + +export function isWebGL(gl: any): gl is WebGLRenderingContext { + return typeof WebGLRenderingContext !== 'undefined' && gl instanceof WebGLRenderingContext +} + +export function isWebGL2(gl: any): gl is WebGL2RenderingContext { + return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext +} + +export interface COMPAT_instanced_arrays { + drawArraysInstanced(mode: number, first: number, count: number, primcount: number): void; + drawElementsInstanced(mode: number, count: number, type: number, offset: number, primcount: number): void; + vertexAttribDivisor(index: number, divisor: number): void; + readonly VERTEX_ATTRIB_ARRAY_DIVISOR: number; +} + +export function getInstancedArrays(gl: GLRenderingContext): COMPAT_instanced_arrays | null { + if (isWebGL2(gl)) { + return { + drawArraysInstanced: gl.drawArraysInstanced.bind(gl), + drawElementsInstanced: gl.drawElementsInstanced.bind(gl), + vertexAttribDivisor: gl.vertexAttribDivisor.bind(gl), + VERTEX_ATTRIB_ARRAY_DIVISOR: gl.VERTEX_ATTRIB_ARRAY_DIVISOR + } + } else { + const ext = gl.getExtension('ANGLE_instanced_arrays') + if (ext === null) return null + return { + drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext), + drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext), + vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext), + VERTEX_ATTRIB_ARRAY_DIVISOR: ext.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE + } + } +} + +export interface COMPAT_standard_derivatives { + readonly FRAGMENT_SHADER_DERIVATIVE_HINT: number; +} + +export function getStandardDerivatives(gl: GLRenderingContext): COMPAT_standard_derivatives | null { + if (isWebGL2(gl)) { + return { FRAGMENT_SHADER_DERIVATIVE_HINT: gl.FRAGMENT_SHADER_DERIVATIVE_HINT } + } else { + const ext = gl.getExtension('OES_standard_derivatives') + if (ext === null) { + throw new Error('Could not get "OES_standard_derivatives" extension') + } + return { FRAGMENT_SHADER_DERIVATIVE_HINT: ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES } + } +} + +export interface COMPAT_element_index_uint { +} + +export function getElementIndexUint(gl: GLRenderingContext): COMPAT_element_index_uint | null { + return isWebGL2(gl) ? {} : gl.getExtension('OES_standard_derivatives') +} + +export interface COMPAT_vertex_array_object { + readonly VERTEX_ARRAY_BINDING: number; + bindVertexArray(arrayObject: WebGLVertexArrayObject | null): void; + createVertexArray(): WebGLVertexArrayObject | null; + deleteVertexArray(arrayObject: WebGLVertexArrayObject): void; + isVertexArray(value: any): value is WebGLVertexArrayObject; +} + +export function getVertexArrayObject(gl: GLRenderingContext): COMPAT_vertex_array_object | null { + if (isWebGL2(gl)) { + return { + VERTEX_ARRAY_BINDING: gl.VERTEX_ARRAY_BINDING, + bindVertexArray: gl.bindVertexArray.bind(gl), + createVertexArray: gl.createVertexArray.bind(gl), + deleteVertexArray: gl.deleteVertexArray.bind(gl), + isVertexArray: gl.isVertexArray.bind(gl) as (value: any) => value is WebGLVertexArrayObject // TODO change when webgl2 types are fixed + } + } else { + const ext = gl.getExtension('OES_vertex_array_object') + if (ext === null) return null + return { + VERTEX_ARRAY_BINDING: ext.VERTEX_ARRAY_BINDING_OES, + bindVertexArray: ext.bindVertexArrayOES.bind(ext), + createVertexArray: ext.createVertexArrayOES.bind(ext), + deleteVertexArray: ext.deleteVertexArrayOES.bind(ext), + isVertexArray: ext.isVertexArrayOES.bind(ext) + } + } +} \ No newline at end of file diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts index 69b99ac5a..0ba44529a 100644 --- a/src/mol-gl/webgl/context.ts +++ b/src/mol-gl/webgl/context.ts @@ -6,12 +6,24 @@ import { createProgramCache, ProgramCache } from './program' 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 } from './compat'; + +export function getGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes): GLRenderingContext | null { + function getContext(contextId: 'webgl' | 'experimental-webgl' | 'webgl2') { + try { + return canvas.getContext(contextId, contextAttributes) as GLRenderingContext | null + } catch (e) { + return null + } + } + return getContext('webgl2') || getContext('webgl') || getContext('experimental-webgl') +} function getPixelRatio() { return (typeof window !== 'undefined') ? window.devicePixelRatio : 1 } -function unbindResources (gl: WebGLRenderingContext) { +function unbindResources (gl: GLRenderingContext) { // bind null to all texture units const maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) for (let i = 0; i < maxTextureImageUnits; ++i) { @@ -35,7 +47,7 @@ function unbindResources (gl: WebGLRenderingContext) { unbindFramebuffer(gl) } -function unbindFramebuffer(gl: WebGLRenderingContext) { +function unbindFramebuffer(gl: GLRenderingContext) { gl.bindFramebuffer(gl.FRAMEBUFFER, null) } @@ -55,20 +67,21 @@ export function createImageData(buffer: Uint8Array, width: number, height: numbe } type Extensions = { - angleInstancedArrays: ANGLE_instanced_arrays - standardDerivatives: OES_standard_derivatives - oesElementIndexUint: OES_element_index_uint | null - oesVertexArrayObject: OES_vertex_array_object | null + instancedArrays: COMPAT_instanced_arrays + standardDerivatives: COMPAT_standard_derivatives + elementIndexUint: COMPAT_element_index_uint | null + vertexArrayObject: COMPAT_vertex_array_object | null } /** A WebGL context object, including the rendering context, resource caches and counts */ export interface Context { - gl: WebGLRenderingContext - extensions: Extensions - pixelRatio: number + readonly gl: GLRenderingContext + readonly isWebGL2: boolean + readonly extensions: Extensions + readonly pixelRatio: number - shaderCache: ShaderCache - programCache: ProgramCache + readonly shaderCache: ShaderCache + readonly programCache: ProgramCache bufferCount: number framebufferCount: number @@ -87,22 +100,24 @@ export interface Context { destroy: () => void } -export function createContext(gl: WebGLRenderingContext): Context { - const angleInstancedArrays = gl.getExtension('ANGLE_instanced_arrays') - if (angleInstancedArrays === null) { - throw new Error('Could not get "ANGLE_instanced_arrays" extension') + + +export function createContext(gl: GLRenderingContext): Context { + const instancedArrays = getInstancedArrays(gl) + if (instancedArrays === null) { + throw new Error('Could not find support for "instanced_arrays"') } - const standardDerivatives = gl.getExtension('OES_standard_derivatives') + const standardDerivatives = getStandardDerivatives(gl) if (standardDerivatives === null) { - throw new Error('Could not get "OES_standard_derivatives" extension') + throw new Error('Could not find support for "standard_derivatives"') } - const oesElementIndexUint = gl.getExtension('OES_element_index_uint') - if (oesElementIndexUint === null) { - console.warn('Could not get "OES_element_index_uint" extension') + const elementIndexUint = getElementIndexUint(gl) + if (elementIndexUint === null) { + console.warn('Could not find support for "element_index_uint"') } - const oesVertexArrayObject = gl.getExtension('OES_vertex_array_object') - if (oesVertexArrayObject === null) { - console.log('Could not get "OES_vertex_array_object" extension') + const vertexArrayObject = getVertexArrayObject(gl) + if (vertexArrayObject === null) { + console.log('Could not find support for "vertex_array_object"') } const shaderCache = createShaderCache() @@ -114,7 +129,8 @@ export function createContext(gl: WebGLRenderingContext): Context { return { gl, - extensions: { angleInstancedArrays, standardDerivatives, oesElementIndexUint, oesVertexArrayObject }, + isWebGL2: isWebGL2(gl), + extensions: { instancedArrays, standardDerivatives, elementIndexUint, vertexArrayObject }, pixelRatio: getPixelRatio(), shaderCache, diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index 9795b85aa..6f3d3e6c8 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -50,7 +50,7 @@ const RenderVariantDefines = { export type RenderVariant = keyof typeof RenderVariantDefines type ProgramVariants = { [k: string]: ReferenceItem<Program> } -type VertexArrayVariants = { [k: string]: WebGLVertexArrayObjectOES | undefined } +type VertexArrayVariants = { [k: string]: WebGLVertexArrayObjectOES | null } interface ValueChanges { attributes: boolean @@ -70,7 +70,7 @@ interface ValueChanges { export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues): RenderItem { const id = getNextRenderItemId() const { programCache } = ctx - const { angleInstancedArrays, oesVertexArrayObject } = ctx.extensions + const { instancedArrays, vertexArrayObject } = ctx.extensions const { attributeValues, defineValues, textureValues, uniformValues } = splitValues(schema, values) const versions = getValueVersions(values) @@ -127,8 +127,8 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S const program = programs[variant].value const vertexArray = vertexArrays[variant] program.setUniforms(uniformValues) - if (oesVertexArrayObject && vertexArray) { - oesVertexArrayObject.bindVertexArrayOES(vertexArray) + if (vertexArrayObject && vertexArray) { + vertexArrayObject.bindVertexArray(vertexArray) // need to bind elements buffer explicitely since it is not always recorded in the VAO if (elementsBuffer) elementsBuffer.bind() } else { @@ -137,9 +137,9 @@ export function createRenderItem(ctx: Context, drawMode: DrawMode, shaderCode: S } program.bindTextures(textures) if (elementsBuffer) { - angleInstancedArrays.drawElementsInstancedANGLE(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount); + instancedArrays.drawElementsInstanced(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount); } else { - angleInstancedArrays.drawArraysInstancedANGLE(glDrawMode, 0, drawCount, instanceCount) + instancedArrays.drawArraysInstanced(glDrawMode, 0, drawCount, instanceCount) } }, update: () => { diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts index 72f0bc3f9..d7e94cc07 100644 --- a/src/mol-gl/webgl/texture.ts +++ b/src/mol-gl/webgl/texture.ts @@ -104,7 +104,7 @@ export function createTexture(ctx: Context, _format: TextureFormat, _type: Textu // unpack alignment of 1 since we use textures only for data gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); // gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, array) + (gl as WebGLRenderingContext).texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, array) // TODO remove cast when webgl2 types are fixed _width = width _height = height gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter) diff --git a/src/mol-gl/webgl/uniform.ts b/src/mol-gl/webgl/uniform.ts index b3dfeb4c9..a8a92ad23 100644 --- a/src/mol-gl/webgl/uniform.ts +++ b/src/mol-gl/webgl/uniform.ts @@ -39,11 +39,11 @@ function createUniformSetter(ctx: Context, program: WebGLProgram, name: string, switch (kind) { case 'f': return (value: number) => gl.uniform1f(location, value) case 'i': case 't2': return (value: number) => gl.uniform1i(location, value) - case 'v2': return (value: Vec2) => gl.uniform2fv(location, value) - case 'v3': return (value: Vec3) => gl.uniform3fv(location, value) - case 'v4': return (value: Vec4) => gl.uniform4fv(location, value) - case 'm3': return (value: Mat3) => gl.uniformMatrix3fv(location, false, value) - case 'm4': return (value: Mat4) => gl.uniformMatrix4fv(location, false, value) + case 'v2': return (value: Vec2) => (gl as WebGLRenderingContext).uniform2fv(location, value) // TODO remove cast when webgl2 types are fixed + case 'v3': return (value: Vec3) => (gl as WebGLRenderingContext).uniform3fv(location, value) + case 'v4': return (value: Vec4) => (gl as WebGLRenderingContext).uniform4fv(location, value) + case 'm3': return (value: Mat3) => (gl as WebGLRenderingContext).uniformMatrix3fv(location, false, value) + case 'm4': return (value: Mat4) => (gl as WebGLRenderingContext).uniformMatrix4fv(location, false, value) } } diff --git a/src/mol-gl/webgl/vertex-array.ts b/src/mol-gl/webgl/vertex-array.ts index aaf92f275..19a2adc2f 100644 --- a/src/mol-gl/webgl/vertex-array.ts +++ b/src/mol-gl/webgl/vertex-array.ts @@ -9,23 +9,23 @@ import { Program } from './program'; import { AttributeBuffers, ElementsBuffer } from './buffer'; export function createVertexArray(ctx: Context, program: Program, attributeBuffers: AttributeBuffers, elementsBuffer?: ElementsBuffer) { - const { oesVertexArrayObject } = ctx.extensions - let vertexArray: WebGLVertexArrayObjectOES | undefined = undefined - if (oesVertexArrayObject) { - vertexArray = oesVertexArrayObject.createVertexArrayOES() - oesVertexArrayObject.bindVertexArrayOES(vertexArray) + const { vertexArrayObject } = ctx.extensions + let vertexArray: WebGLVertexArrayObject | null = null + if (vertexArrayObject) { + vertexArray = vertexArrayObject.createVertexArray() + vertexArrayObject.bindVertexArray(vertexArray) if (elementsBuffer) elementsBuffer.bind() program.bindAttributes(attributeBuffers) ctx.vaoCount += 1 - oesVertexArrayObject.bindVertexArrayOES(null!) + vertexArrayObject.bindVertexArray(null!) } return vertexArray } -export function deleteVertexArray(ctx: Context, vertexArray?: WebGLVertexArrayObjectOES) { - const { oesVertexArrayObject } = ctx.extensions - if (oesVertexArrayObject && vertexArray) { - oesVertexArrayObject.deleteVertexArrayOES(vertexArray) +export function deleteVertexArray(ctx: Context, vertexArray: WebGLVertexArrayObject | null) { + const { vertexArrayObject } = ctx.extensions + if (vertexArrayObject && vertexArray) { + vertexArrayObject.deleteVertexArray(vertexArray) ctx.vaoCount -= 1 } } \ No newline at end of file diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts index fd4f1ec27..91a42cdac 100644 --- a/src/mol-view/viewer.ts +++ b/src/mol-view/viewer.ts @@ -16,7 +16,7 @@ import TrackballControls from './controls/trackball' import { Viewport } from './camera/util' import { PerspectiveCamera } from './camera/perspective' import { resizeCanvas } from './util'; -import { createContext } from 'mol-gl/webgl/context'; +import { createContext, getGLContext } from 'mol-gl/webgl/context'; import { Representation } from 'mol-geo/representation'; import { createRenderTarget } from 'mol-gl/webgl/render-target'; import Scene from 'mol-gl/scene'; @@ -59,17 +59,6 @@ interface Viewer { dispose: () => void } -function getWebGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes) { - function getContext(contextId: 'webgl' | 'experimental-webgl') { - try { - return canvas.getContext(contextId, contextAttributes) - } catch (e) { - return null - } - } - return getContext('webgl') || getContext('experimental-webgl') -} - namespace Viewer { export function create(canvas: HTMLCanvasElement, container: Element): Viewer { const reprMap = new Map<Representation<any>, Set<RenderObject>>() @@ -87,7 +76,7 @@ namespace Viewer { }) // camera.lookAt(Vec3.create(0, 0, 0)) - const gl = getWebGLContext(canvas, { + const gl = getGLContext(canvas, { alpha: false, antialias: true, depth: true, diff --git a/tsconfig.json b/tsconfig.json index 31421faf7..413bfe585 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,5 +29,8 @@ "mol-view": ["./mol-view"] } }, - "include": [ "**/*" ] + "include": [ "**/*" ], + "files": [ + "./node_modules/@types/webgl2/index.d.ts" + ], } \ No newline at end of file -- GitLab