UNPKG

molstar

Version:

A comprehensive macromolecular library.

608 lines (605 loc) 22.5 kB
"use strict"; /** * Copyright (c) 2018-2024 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.isWebGL = isWebGL; exports.isWebGL2 = isWebGL2; exports.getInstancedArrays = getInstancedArrays; exports.getStandardDerivatives = getStandardDerivatives; exports.getElementIndexUint = getElementIndexUint; exports.getVertexArrayObject = getVertexArrayObject; exports.getTextureFloat = getTextureFloat; exports.getTextureFloatLinear = getTextureFloatLinear; exports.getTextureHalfFloat = getTextureHalfFloat; exports.getTextureHalfFloatLinear = getTextureHalfFloatLinear; exports.getBlendMinMax = getBlendMinMax; exports.getFragDepth = getFragDepth; exports.getColorBufferFloat = getColorBufferFloat; exports.getColorBufferHalfFloat = getColorBufferHalfFloat; exports.getDrawBuffers = getDrawBuffers; exports.getDrawBuffersIndexed = getDrawBuffersIndexed; exports.getShaderTextureLod = getShaderTextureLod; exports.getDepthTexture = getDepthTexture; exports.getSRGB = getSRGB; exports.getDisjointTimerQuery = getDisjointTimerQuery; exports.getMultiDraw = getMultiDraw; exports.getDrawInstancedBaseVertexBaseInstance = getDrawInstancedBaseVertexBaseInstance; exports.getMultiDrawInstancedBaseVertexBaseInstance = getMultiDrawInstancedBaseVertexBaseInstance; exports.getParallelShaderCompile = getParallelShaderCompile; exports.getFboRenderMipmap = getFboRenderMipmap; exports.getProvokingVertex = getProvokingVertex; exports.getClipCullDistance = getClipCullDistance; exports.getConservativeDepth = getConservativeDepth; exports.getStencilTexturing = getStencilTexturing; exports.getClipControl = getClipControl; exports.getRenderSnorm = getRenderSnorm; exports.getRenderSharedExponent = getRenderSharedExponent; exports.getTextureNorm16 = getTextureNorm16; exports.getDepthClamp = getDepthClamp; exports.getNoNonInstancedActiveAttribs = getNoNonInstancedActiveAttribs; exports.testColorBuffer = testColorBuffer; const debug_1 = require("../../mol-util/debug"); const context_1 = require("./context"); const program_1 = require("./program"); const shader_1 = require("./shader"); function isWebGL(gl) { return typeof WebGLRenderingContext !== 'undefined' && gl instanceof WebGLRenderingContext; } function isWebGL2(gl) { return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; } function getInstancedArrays(gl) { 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 }; } } function getStandardDerivatives(gl) { if (isWebGL2(gl)) { return { FRAGMENT_SHADER_DERIVATIVE_HINT: gl.FRAGMENT_SHADER_DERIVATIVE_HINT }; } else { const ext = gl.getExtension('OES_standard_derivatives'); if (ext === null) return null; return { FRAGMENT_SHADER_DERIVATIVE_HINT: ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES }; } } function getElementIndexUint(gl) { return isWebGL2(gl) ? {} : gl.getExtension('OES_element_index_uint'); } function getVertexArrayObject(gl) { 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) }; } 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) }; } } function getTextureFloat(gl) { return isWebGL2(gl) ? {} : gl.getExtension('OES_texture_float'); } function getTextureFloatLinear(gl) { return gl.getExtension('OES_texture_float_linear'); } function getTextureHalfFloat(gl) { if (isWebGL2(gl)) { return { HALF_FLOAT: gl.HALF_FLOAT }; } else { const ext = gl.getExtension('OES_texture_half_float'); if (ext === null) return null; return { HALF_FLOAT: ext.HALF_FLOAT_OES }; } } function getTextureHalfFloatLinear(gl) { return gl.getExtension('OES_texture_half_float_linear'); } function getBlendMinMax(gl) { if (isWebGL2(gl)) { return { MIN: gl.MIN, MAX: gl.MAX }; } else { const ext = gl.getExtension('EXT_blend_minmax'); if (ext === null) return null; return { MIN: ext.MIN_EXT, MAX: ext.MAX_EXT }; } } function getFragDepth(gl) { return isWebGL2(gl) ? {} : gl.getExtension('EXT_frag_depth'); } function getColorBufferFloat(gl) { if (isWebGL2(gl)) { if (gl.getExtension('EXT_color_buffer_float') === null) return null; gl.getExtension('EXT_float_blend'); return { RGBA32F: gl.RGBA32F }; } else { const ext = gl.getExtension('WEBGL_color_buffer_float'); if (ext === null) { // test as support may not be advertised by browsers gl.getExtension('OES_texture_float'); return testColorBuffer(gl, gl.FLOAT) ? { RGBA32F: 0x8814 } : null; } gl.getExtension('EXT_float_blend'); return { RGBA32F: ext.RGBA32F_EXT }; } } function getColorBufferHalfFloat(gl) { if (isWebGL2(gl)) { if (gl.getExtension('EXT_color_buffer_half_float') === null) return null; gl.getExtension('EXT_float_blend'); return { RGBA16F: gl.RGBA16F }; } else { const ext = gl.getExtension('EXT_color_buffer_half_float'); if (ext === null) { // test as support may not be advertised by browsers gl.getExtension('OES_texture_half_float'); return testColorBuffer(gl, 0x8D61) ? { RGBA16F: 0x881A } : null; } gl.getExtension('EXT_float_blend'); return { RGBA16F: ext.RGBA16F_EXT }; } } function getDrawBuffers(gl) { if (isWebGL2(gl)) { return { drawBuffers: gl.drawBuffers.bind(gl), COLOR_ATTACHMENT0: gl.COLOR_ATTACHMENT0, COLOR_ATTACHMENT1: gl.COLOR_ATTACHMENT1, COLOR_ATTACHMENT2: gl.COLOR_ATTACHMENT2, COLOR_ATTACHMENT3: gl.COLOR_ATTACHMENT3, COLOR_ATTACHMENT4: gl.COLOR_ATTACHMENT4, COLOR_ATTACHMENT5: gl.COLOR_ATTACHMENT5, COLOR_ATTACHMENT6: gl.COLOR_ATTACHMENT6, COLOR_ATTACHMENT7: gl.COLOR_ATTACHMENT7, DRAW_BUFFER0: gl.DRAW_BUFFER0, DRAW_BUFFER1: gl.DRAW_BUFFER1, DRAW_BUFFER2: gl.DRAW_BUFFER2, DRAW_BUFFER3: gl.DRAW_BUFFER3, DRAW_BUFFER4: gl.DRAW_BUFFER4, DRAW_BUFFER5: gl.DRAW_BUFFER5, DRAW_BUFFER6: gl.DRAW_BUFFER6, DRAW_BUFFER7: gl.DRAW_BUFFER7, MAX_COLOR_ATTACHMENTS: gl.MAX_COLOR_ATTACHMENTS, MAX_DRAW_BUFFERS: gl.MAX_DRAW_BUFFERS, }; } else { const ext = gl.getExtension('WEBGL_draw_buffers'); if (ext === null) return null; return { drawBuffers: ext.drawBuffersWEBGL.bind(ext), COLOR_ATTACHMENT0: ext.COLOR_ATTACHMENT0_WEBGL, COLOR_ATTACHMENT1: ext.COLOR_ATTACHMENT1_WEBGL, COLOR_ATTACHMENT2: ext.COLOR_ATTACHMENT2_WEBGL, COLOR_ATTACHMENT3: ext.COLOR_ATTACHMENT3_WEBGL, COLOR_ATTACHMENT4: ext.COLOR_ATTACHMENT4_WEBGL, COLOR_ATTACHMENT5: ext.COLOR_ATTACHMENT5_WEBGL, COLOR_ATTACHMENT6: ext.COLOR_ATTACHMENT6_WEBGL, COLOR_ATTACHMENT7: ext.COLOR_ATTACHMENT7_WEBGL, DRAW_BUFFER0: ext.DRAW_BUFFER0_WEBGL, DRAW_BUFFER1: ext.DRAW_BUFFER1_WEBGL, DRAW_BUFFER2: ext.DRAW_BUFFER2_WEBGL, DRAW_BUFFER3: ext.DRAW_BUFFER3_WEBGL, DRAW_BUFFER4: ext.DRAW_BUFFER4_WEBGL, DRAW_BUFFER5: ext.DRAW_BUFFER5_WEBGL, DRAW_BUFFER6: ext.DRAW_BUFFER6_WEBGL, DRAW_BUFFER7: ext.DRAW_BUFFER7_WEBGL, MAX_COLOR_ATTACHMENTS: ext.MAX_COLOR_ATTACHMENTS_WEBGL, MAX_DRAW_BUFFERS: ext.MAX_DRAW_BUFFERS_WEBGL, }; } } function getDrawBuffersIndexed(gl) { const ext = gl.getExtension('OES_draw_buffers_indexed'); if (ext === null) return null; return { enablei: ext.enableiOES.bind(ext), disablei: ext.disableiOES.bind(ext), blendEquationi: ext.blendEquationiOES.bind(ext), blendEquationSeparatei: ext.blendEquationSeparateiOES.bind(ext), blendFunci: ext.blendFunciOES.bind(ext), blendFuncSeparatei: ext.blendFuncSeparateiOES.bind(ext), colorMaski: ext.colorMaskiOES.bind(ext), }; } function getShaderTextureLod(gl) { return isWebGL2(gl) ? {} : gl.getExtension('EXT_shader_texture_lod'); } function getDepthTexture(gl) { if (isWebGL2(gl)) { return { UNSIGNED_INT_24_8: gl.UNSIGNED_INT_24_8 }; } else { const ext = gl.getExtension('WEBGL_depth_texture'); if (ext === null) return null; return { UNSIGNED_INT_24_8: ext.UNSIGNED_INT_24_8_WEBGL }; } } function getSRGB(gl) { if (isWebGL2(gl)) { return { FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, SRGB8_ALPHA8: gl.SRGB8_ALPHA8, SRGB8: gl.SRGB8, SRGB: gl.SRGB }; } else { const ext = gl.getExtension('EXT_sRGB'); if (ext === null) return null; return { FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT, SRGB8_ALPHA8: ext.SRGB8_ALPHA8_EXT, SRGB8: ext.SRGB_ALPHA_EXT, SRGB: ext.SRGB_EXT }; } } function getDisjointTimerQuery(gl) { if (isWebGL2(gl)) { // Firefox has EXT_disjoint_timer_query in webgl2 const ext = gl.getExtension('EXT_disjoint_timer_query_webgl2') || gl.getExtension('EXT_disjoint_timer_query'); if (ext === null) return null; return { QUERY_COUNTER_BITS: ext.QUERY_COUNTER_BITS_EXT, CURRENT_QUERY: gl.CURRENT_QUERY, QUERY_RESULT: gl.QUERY_RESULT, QUERY_RESULT_AVAILABLE: gl.QUERY_RESULT_AVAILABLE, TIME_ELAPSED: ext.TIME_ELAPSED_EXT, TIMESTAMP: ext.TIMESTAMP_EXT, GPU_DISJOINT: ext.GPU_DISJOINT_EXT, createQuery: gl.createQuery.bind(gl), deleteQuery: gl.deleteQuery.bind(gl), isQuery: gl.isQuery.bind(gl), beginQuery: gl.beginQuery.bind(gl), endQuery: gl.endQuery.bind(gl), queryCounter: ext.queryCounterEXT.bind(ext), getQuery: gl.getQuery.bind(gl), getQueryParameter: gl.getQueryParameter.bind(gl), }; } else { const ext = gl.getExtension('EXT_disjoint_timer_query'); if (ext === null) return null; return { QUERY_COUNTER_BITS: ext.QUERY_COUNTER_BITS_EXT, CURRENT_QUERY: ext.CURRENT_QUERY_EXT, QUERY_RESULT: ext.QUERY_RESULT_EXT, QUERY_RESULT_AVAILABLE: ext.QUERY_RESULT_AVAILABLE_EXT, TIME_ELAPSED: ext.TIME_ELAPSED_EXT, TIMESTAMP: ext.TIMESTAMP_EXT, GPU_DISJOINT: ext.GPU_DISJOINT_EXT, createQuery: ext.createQueryEXT.bind(ext), deleteQuery: ext.deleteQueryEXT.bind(ext), isQuery: ext.isQueryEXT.bind(ext), beginQuery: ext.beginQueryEXT.bind(ext), endQuery: ext.endQueryEXT.bind(ext), queryCounter: ext.queryCounterEXT.bind(ext), getQuery: ext.getQueryEXT.bind(ext), getQueryParameter: ext.getQueryObjectEXT.bind(ext), }; } } function getMultiDraw(gl) { const ext = gl.getExtension('WEBGL_multi_draw'); if (ext) { return { multiDrawArrays: ext.multiDrawArraysWEBGL.bind(ext), multiDrawElements: ext.multiDrawElementsWEBGL.bind(ext), multiDrawArraysInstanced: ext.multiDrawArraysInstancedWEBGL.bind(ext), multiDrawElementsInstanced: ext.multiDrawElementsInstancedWEBGL.bind(ext), }; } else { return null; } } function getDrawInstancedBaseVertexBaseInstance(gl) { const ext = gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance'); if (ext) { return { drawArraysInstancedBaseInstance: ext.drawArraysInstancedBaseInstanceWEBGL.bind(ext), drawElementsInstancedBaseVertexBaseInstance: ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL.bind(ext), }; } else { return null; } } function getMultiDrawInstancedBaseVertexBaseInstance(gl) { const ext = gl.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance'); if (ext) { return { multiDrawArraysInstancedBaseInstance: ext.multiDrawArraysInstancedBaseInstanceWEBGL.bind(ext), multiDrawElementsInstancedBaseVertexBaseInstance: ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL.bind(ext), }; } else { return null; } } function getParallelShaderCompile(gl) { const ext = gl.getExtension('KHR_parallel_shader_compile'); if (ext === null) return null; return { COMPLETION_STATUS: ext.COMPLETION_STATUS_KHR, }; } function getFboRenderMipmap(gl) { return isWebGL2(gl) ? {} : gl.getExtension('OES_fbo_render_mipmap'); } function getProvokingVertex(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('WEBGL_provoking_vertex'); if (ext) { return { FIRST_VERTEX_CONVENTION: ext.FIRST_VERTEX_CONVENTION_WEBGL, LAST_VERTEX_CONVENTION: ext.LAST_VERTEX_CONVENTION_WEBGL, PROVOKING_VERTEX: ext.PROVOKING_VERTEX_WEBGL, provokingVertex: ext.provokingVertexWEBGL.bind(ext) }; } } return null; } function getClipCullDistance(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('WEBGL_clip_cull_distance'); if (ext) { return { MAX_CLIP_DISTANCES: ext.MAX_CLIP_DISTANCES_WEBGL, MAX_CULL_DISTANCES: ext.MAX_CULL_DISTANCES_WEBGL, MAX_COMBINED_CLIP_AND_CULL_DISTANCES: ext.MAX_COMBINED_CLIP_AND_CULL_DISTANCES_WEBGL, CLIP_DISTANCE0: ext.CLIP_DISTANCE0_WEBGL, CLIP_DISTANCE1: ext.CLIP_DISTANCE1_WEBGL, CLIP_DISTANCE2: ext.CLIP_DISTANCE2_WEBGL, CLIP_DISTANCE3: ext.CLIP_DISTANCE3_WEBGL, CLIP_DISTANCE4: ext.CLIP_DISTANCE4_WEBGL, CLIP_DISTANCE5: ext.CLIP_DISTANCE5_WEBGL, CLIP_DISTANCE6: ext.CLIP_DISTANCE6_WEBGL, CLIP_DISTANCE7: ext.CLIP_DISTANCE7_WEBGL }; } } return null; } function getConservativeDepth(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('EXT_conservative_depth'); if (ext) { return {}; } } return null; } function getStencilTexturing(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('WEBGL_stencil_texturing'); if (ext) { return { DEPTH_STENCIL_TEXTURE_MODE: ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, STENCIL_INDEX: ext.STENCIL_INDEX_WEBGL }; } } return null; } function getClipControl(gl) { const ext = gl.getExtension('EXT_clip_control'); if (ext) { return { LOWER_LEFT: ext.LOWER_LEFT_EXT, UPPER_LEFT: ext.UPPER_LEFT_EXT, NEGATIVE_ONE_TO_ONE: ext.NEGATIVE_ONE_TO_ONE_EXT, ZERO_TO_ONE: ext.ZERO_TO_ONE_EXT, CLIP_ORIGIN: ext.CLIP_ORIGIN_EXT, CLIP_DEPTH_MODE: ext.CLIP_DEPTH_MODE_EXT, clipControl: ext.clipControlEXT.bind(ext) }; } return null; } function getRenderSnorm(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('EXT_render_snorm'); if (ext) { return {}; } } return null; } function getRenderSharedExponent(gl) { if (isWebGL2(gl)) { const ext = gl.getExtension('WEBGL_render_shared_exponent'); if (ext) { return {}; } } return null; } function getTextureNorm16(gl) { const ext = gl.getExtension('EXT_texture_norm16'); if (ext) { return { R16: ext.R16_EXT, RG16: ext.RG16_EXT, RGB16: ext.RGB16_EXT, RGBA16: ext.RGBA16_EXT, R16_SNORM: ext.R16_SNORM_EXT, RG16_SNORM: ext.RG16_SNORM_EXT, RGB16_SNORM: ext.RGB16_SNORM_EXT, RGBA16_SNORM: ext.RGBA16_SNORM_EXT }; } return null; } function getDepthClamp(gl) { const ext = gl.getExtension('EXT_depth_clamp'); if (ext) { return { DEPTH_CLAMP: ext.DEPTH_CLAMP_EXT }; } return null; } function getNoNonInstancedActiveAttribs(gl) { if (!isWebGL2(gl)) return false; if (typeof navigator !== 'undefined') { const ffMatch = window.navigator.userAgent.match(/Firefox\/([0-9]+)\./); if (!ffMatch) return true; const ffVersion = parseInt(ffMatch[1]); // supported since FF 85 (https://bugzilla.mozilla.org/show_bug.cgi?id=1679693) return ffVersion >= 85; } return false; } // const TextureTestVertShader = ` attribute vec4 aPosition; void main() { gl_Position = aPosition; }`; const TextureTestFragShader = ` precision mediump float; uniform vec4 uColor; uniform sampler2D uTexture; void main() { gl_FragColor = texture2D(uTexture, vec2(0.5, 0.5)) * uColor; }`; const TextureTestTexCoords = new Float32Array([ -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0 ]); // adapted from https://stackoverflow.com/questions/28827511/ function testColorBuffer(gl, type) { // setup shaders const vertShader = (0, shader_1.getShader)(gl, { type: 'vert', source: TextureTestVertShader }); const fragShader = (0, shader_1.getShader)(gl, { type: 'frag', source: TextureTestFragShader }); if (!vertShader || !fragShader) return false; // setup program const program = (0, program_1.getProgram)(gl); gl.attachShader(program, vertShader); gl.attachShader(program, fragShader); gl.linkProgram(program); gl.useProgram(program); // look up where the vertex data needs to go. const positionLocation = gl.getAttribLocation(program, 'aPosition'); const colorLoc = gl.getUniformLocation(program, 'uColor'); if (!colorLoc) { if (debug_1.isDebugMode) { console.log(`error getting 'uColor' uniform location`); } return false; } // provide texture coordinates for the rectangle. const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, TextureTestTexCoords, gl.STATIC_DRAW); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); const whiteTex = gl.createTexture(); const whiteData = new Uint8Array([255, 255, 255, 255]); gl.bindTexture(gl.TEXTURE_2D, whiteTex); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, whiteData); const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, type, null); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); const fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); if (status !== gl.FRAMEBUFFER_COMPLETE) { if (debug_1.isDebugMode) { console.log(`error creating framebuffer for '${type}'`); } return false; } // Draw the rectangle. gl.bindTexture(gl.TEXTURE_2D, whiteTex); gl.uniform4fv(colorLoc, [0, 10, 20, 1]); gl.drawArrays(gl.TRIANGLES, 0, 6); gl.bindTexture(gl.TEXTURE_2D, tex); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(1, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform4fv(colorLoc, [0, 1 / 10, 1 / 20, 1]); gl.drawArrays(gl.TRIANGLES, 0, 6); // Check if rendered correctly const pixel = new Uint8Array(4); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); if (pixel[0] !== 0 || pixel[1] < 248 || pixel[2] < 248 || pixel[3] < 254) { if (debug_1.isDebugMode) { console.log(`not able to actually render to '${type}' texture`); } return false; } // Check reading from float texture if (type === gl.FLOAT) { gl.bindFramebuffer(gl.FRAMEBUFFER, fb); const floatPixel = new Float32Array(4); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatPixel); const error = gl.getError(); if (error) { if (debug_1.isDebugMode) { console.log(`error reading float pixels: '${(0, context_1.getErrorDescription)(gl, error)}'`); } return false; } } return true; }