molstar
Version:
A comprehensive macromolecular library.
608 lines (605 loc) • 22.5 kB
JavaScript
"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;
}