UNPKG

molstar

Version:

A comprehensive macromolecular library.

382 lines (380 loc) 18.2 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> * @author Gianluca Tomasello <giagitom@gmail.com> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ImageShaderCode = exports.DirectVolumeShaderCode = exports.MeshShaderCode = exports.LinesShaderCode = exports.TextShaderCode = exports.CylindersShaderCode = exports.SpheresShaderCode = exports.PointsShaderCode = void 0; exports.ShaderCode = ShaderCode; exports.addShaderDefines = addShaderDefines; const id_factory_1 = require("../mol-util/id-factory"); const compat_1 = require("./webgl/compat"); const type_helpers_1 = require("../mol-util/type-helpers"); const shaderCodeId = (0, id_factory_1.idFactory)(); const apply_fog_glsl_1 = require("./shader/chunks/apply-fog.glsl"); const apply_interior_color_glsl_1 = require("./shader/chunks/apply-interior-color.glsl"); const apply_light_color_glsl_1 = require("./shader/chunks/apply-light-color.glsl"); const apply_marker_color_glsl_1 = require("./shader/chunks/apply-marker-color.glsl"); const assign_clipping_varying_glsl_1 = require("./shader/chunks/assign-clipping-varying.glsl"); const assign_color_varying_glsl_1 = require("./shader/chunks/assign-color-varying.glsl"); const assign_group_glsl_1 = require("./shader/chunks/assign-group.glsl"); const assign_marker_varying_glsl_1 = require("./shader/chunks/assign-marker-varying.glsl"); const assign_material_color_glsl_1 = require("./shader/chunks/assign-material-color.glsl"); const assign_position_glsl_1 = require("./shader/chunks/assign-position.glsl"); const assign_size_glsl_1 = require("./shader/chunks/assign-size.glsl"); const check_picking_alpha_glsl_1 = require("./shader/chunks/check-picking-alpha.glsl"); const check_transparency_glsl_1 = require("./shader/chunks/check-transparency.glsl"); const clip_instance_glsl_1 = require("./shader/chunks/clip-instance.glsl"); const clip_pixel_glsl_1 = require("./shader/chunks/clip-pixel.glsl"); const color_frag_params_glsl_1 = require("./shader/chunks/color-frag-params.glsl"); const color_vert_params_glsl_1 = require("./shader/chunks/color-vert-params.glsl"); const common_clip_glsl_1 = require("./shader/chunks/common-clip.glsl"); const common_frag_params_glsl_1 = require("./shader/chunks/common-frag-params.glsl"); const common_vert_params_glsl_1 = require("./shader/chunks/common-vert-params.glsl"); const common_glsl_1 = require("./shader/chunks/common.glsl"); const fade_lod_glsl_1 = require("./shader/chunks/fade-lod.glsl"); const float_to_rgba_glsl_1 = require("./shader/chunks/float-to-rgba.glsl"); const light_frag_params_glsl_1 = require("./shader/chunks/light-frag-params.glsl"); const matrix_scale_glsl_1 = require("./shader/chunks/matrix-scale.glsl"); const normal_frag_params_glsl_1 = require("./shader/chunks/normal-frag-params.glsl"); const read_from_texture_glsl_1 = require("./shader/chunks/read-from-texture.glsl"); const rgba_to_float_glsl_1 = require("./shader/chunks/rgba-to-float.glsl"); const size_vert_params_glsl_1 = require("./shader/chunks/size-vert-params.glsl"); const texture3d_from_1d_trilinear_glsl_1 = require("./shader/chunks/texture3d-from-1d-trilinear.glsl"); const texture3d_from_2d_linear_glsl_1 = require("./shader/chunks/texture3d-from-2d-linear.glsl"); const texture3d_from_2d_nearest_glsl_1 = require("./shader/chunks/texture3d-from-2d-nearest.glsl"); const wboit_write_glsl_1 = require("./shader/chunks/wboit-write.glsl"); const dpoit_write_glsl_1 = require("./shader/chunks/dpoit-write.glsl"); const ShaderChunks = { apply_fog: apply_fog_glsl_1.apply_fog, apply_interior_color: apply_interior_color_glsl_1.apply_interior_color, apply_light_color: apply_light_color_glsl_1.apply_light_color, apply_marker_color: apply_marker_color_glsl_1.apply_marker_color, assign_clipping_varying: assign_clipping_varying_glsl_1.assign_clipping_varying, assign_color_varying: assign_color_varying_glsl_1.assign_color_varying, assign_group: assign_group_glsl_1.assign_group, assign_marker_varying: assign_marker_varying_glsl_1.assign_marker_varying, assign_material_color: assign_material_color_glsl_1.assign_material_color, assign_position: assign_position_glsl_1.assign_position, assign_size: assign_size_glsl_1.assign_size, check_picking_alpha: check_picking_alpha_glsl_1.check_picking_alpha, check_transparency: check_transparency_glsl_1.check_transparency, clip_instance: clip_instance_glsl_1.clip_instance, clip_pixel: clip_pixel_glsl_1.clip_pixel, color_frag_params: color_frag_params_glsl_1.color_frag_params, color_vert_params: color_vert_params_glsl_1.color_vert_params, common_clip: common_clip_glsl_1.common_clip, common_frag_params: common_frag_params_glsl_1.common_frag_params, common_vert_params: common_vert_params_glsl_1.common_vert_params, common: common_glsl_1.common, fade_lod: fade_lod_glsl_1.fade_lod, float_to_rgba: float_to_rgba_glsl_1.float_to_rgba, light_frag_params: light_frag_params_glsl_1.light_frag_params, matrix_scale: matrix_scale_glsl_1.matrix_scale, normal_frag_params: normal_frag_params_glsl_1.normal_frag_params, read_from_texture: read_from_texture_glsl_1.read_from_texture, rgba_to_float: rgba_to_float_glsl_1.rgba_to_float, size_vert_params: size_vert_params_glsl_1.size_vert_params, texture3d_from_1d_trilinear: texture3d_from_1d_trilinear_glsl_1.texture3d_from_1d_trilinear, texture3d_from_2d_linear: texture3d_from_2d_linear_glsl_1.texture3d_from_2d_linear, texture3d_from_2d_nearest: texture3d_from_2d_nearest_glsl_1.texture3d_from_2d_nearest, wboit_write: wboit_write_glsl_1.wboit_write, dpoit_write: dpoit_write_glsl_1.dpoit_write }; const reInclude = /^(?!\/\/)\s*#include\s+(\S+)/gm; const reUnrollLoop = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*\+\+i\s*\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g; const reSingleLineComment = /[ \t]*\/\/.*\n/g; const reMultiLineComment = /[ \t]*\/\*[\s\S]*?\*\//g; const reMultipleLinebreaks = /\n{2,}/g; function addIncludes(text) { return text .replace(reInclude, (_, p1) => { const chunk = ShaderChunks[p1]; if (!chunk) throw new Error(`empty chunk, '${p1}'`); return chunk; }) .trim() .replace(reSingleLineComment, '\n') .replace(reMultiLineComment, '\n') .replace(reMultipleLinebreaks, '\n'); } function unrollLoops(str) { return str.replace(reUnrollLoop, loopReplacer); } function loopReplacer(_match, start, end, snippet) { let out = ''; for (let i = parseInt(start); i < parseInt(end); ++i) { out += snippet .replace(/\[\s*i\s*\]/g, `[${i}]`) .replace(/UNROLLED_LOOP_INDEX/g, `${i}`); } return out; } function replaceCounts(str, defines) { if (defines.dLightCount) str = str.replace(/dLightCount/g, `${defines.dLightCount.ref.value}`); if (defines.dClipObjectCount) str = str.replace(/dClipObjectCount/g, `${defines.dClipObjectCount.ref.value}`); return str; } function preprocess(str, defines) { return unrollLoops(replaceCounts(str, defines)); } function ShaderCode(name, vert, frag, extensions = {}, outTypes = {}, ignoreDefine) { return { id: shaderCodeId(), name, vert: addIncludes(vert), frag: addIncludes(frag), extensions, outTypes, ignoreDefine }; } // Note: `drawBuffers` need to be 'optional' for wboit function ignoreDefine(name, variant, defines) { var _a; if (variant.startsWith('color') || variant === 'tracing') { if (name === 'dLightCount') { return !!((_a = defines.dIgnoreLight) === null || _a === void 0 ? void 0 : _a.ref.value); } } else { const ignore = [ 'dColorType', 'dUsePalette', 'dOverpaintType', 'dOverpaint', 'dSubstanceType', 'dSubstance', 'dColorMarker', 'dCelShaded', 'dLightCount', ]; if (variant !== 'depth') { ignore.push('dXrayShaded'); } if (variant !== 'emissive') { ignore.push('dEmissiveType', 'dEmissive'); } return ignore.includes(name); } return false; } ; function ignoreDefineUnlit(name, variant, defines) { if (name === 'dLightCount') return true; return ignoreDefine(name, variant, defines); } ; const points_vert_1 = require("./shader/points.vert"); const points_frag_1 = require("./shader/points.frag"); exports.PointsShaderCode = ShaderCode('points', points_vert_1.points_vert, points_frag_1.points_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit); const spheres_vert_1 = require("./shader/spheres.vert"); const spheres_frag_1 = require("./shader/spheres.frag"); exports.SpheresShaderCode = ShaderCode('spheres', spheres_vert_1.spheres_vert, spheres_frag_1.spheres_frag, { fragDepth: 'required', drawBuffers: 'optional' }, {}, ignoreDefine); const cylinders_vert_1 = require("./shader/cylinders.vert"); const cylinders_frag_1 = require("./shader/cylinders.frag"); exports.CylindersShaderCode = ShaderCode('cylinders', cylinders_vert_1.cylinders_vert, cylinders_frag_1.cylinders_frag, { fragDepth: 'required', drawBuffers: 'optional' }, {}, ignoreDefine); const text_vert_1 = require("./shader/text.vert"); const text_frag_1 = require("./shader/text.frag"); exports.TextShaderCode = ShaderCode('text', text_vert_1.text_vert, text_frag_1.text_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit); const lines_vert_1 = require("./shader/lines.vert"); const lines_frag_1 = require("./shader/lines.frag"); exports.LinesShaderCode = ShaderCode('lines', lines_vert_1.lines_vert, lines_frag_1.lines_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit); const mesh_vert_1 = require("./shader/mesh.vert"); const mesh_frag_1 = require("./shader/mesh.frag"); exports.MeshShaderCode = ShaderCode('mesh', mesh_vert_1.mesh_vert, mesh_frag_1.mesh_frag, { drawBuffers: 'optional' }, {}, ignoreDefine); const direct_volume_vert_1 = require("./shader/direct-volume.vert"); const direct_volume_frag_1 = require("./shader/direct-volume.frag"); exports.DirectVolumeShaderCode = ShaderCode('direct-volume', direct_volume_vert_1.directVolume_vert, direct_volume_frag_1.directVolume_frag, { fragDepth: 'optional', drawBuffers: 'optional' }, {}, ignoreDefine); const image_vert_1 = require("./shader/image.vert"); const image_frag_1 = require("./shader/image.frag"); exports.ImageShaderCode = ShaderCode('image', image_vert_1.image_vert, image_frag_1.image_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit); function getDefinesCode(defines, ignore) { var _a; if (defines === undefined) return ''; const variant = (((_a = defines.dRenderVariant) === null || _a === void 0 ? void 0 : _a.ref.value) || ''); const lines = []; for (const name in defines) { if (ignore === null || ignore === void 0 ? void 0 : ignore(name, variant, defines)) continue; const define = defines[name]; const v = define.ref.value; if (v !== undefined) { if (typeof v === 'string') { lines.push(`#define ${name}_${v}`); } else if (typeof v === 'number') { lines.push(`#define ${name} ${v}`); } else if (typeof v === 'boolean') { if (v) lines.push(`#define ${name}`); } else { (0, type_helpers_1.assertUnreachable)(v); } } } return lines.join('\n') + '\n'; } function getGlsl100VertPrefix(extensions, shaderExtensions) { const prefix = []; if (shaderExtensions.drawBuffers) { if (extensions.drawBuffers) { prefix.push('#define requiredDrawBuffers'); } else if (shaderExtensions.drawBuffers === 'required') { throw new Error(`required 'GL_EXT_draw_buffers' extension not available`); } } if (shaderExtensions.multiDraw) { if (extensions.multiDraw) { prefix.push('#extension GL_ANGLE_multi_draw : require'); prefix.push('#define enabledMultiDraw'); } else if (shaderExtensions.multiDraw === 'required') { throw new Error(`required 'GL_ANGLE_multi_draw' extension not available`); } } return prefix.join('\n') + '\n'; } function getGlsl100FragPrefix(extensions, shaderExtensions) { const prefix = [ '#extension GL_OES_standard_derivatives : enable' ]; if (shaderExtensions.fragDepth) { if (extensions.fragDepth) { prefix.push('#extension GL_EXT_frag_depth : enable'); prefix.push('#define enabledFragDepth'); } else if (shaderExtensions.fragDepth === 'required') { throw new Error(`required 'GL_EXT_frag_depth' extension not available`); } } if (shaderExtensions.drawBuffers) { if (extensions.drawBuffers) { prefix.push('#extension GL_EXT_draw_buffers : require'); prefix.push('#define requiredDrawBuffers'); prefix.push('#define gl_FragColor gl_FragData[0]'); } else if (shaderExtensions.drawBuffers === 'required') { throw new Error(`required 'GL_EXT_draw_buffers' extension not available`); } } if (shaderExtensions.shaderTextureLod) { if (extensions.shaderTextureLod) { prefix.push('#extension GL_EXT_shader_texture_lod : enable'); prefix.push('#define enabledShaderTextureLod'); } else if (shaderExtensions.shaderTextureLod === 'required') { throw new Error(`required 'GL_EXT_shader_texture_lod' extension not available`); } } if (extensions.depthTexture) { prefix.push('#define depthTextureSupport'); } return prefix.join('\n') + '\n'; } const glsl300VertPrefixCommon = ` #define attribute in #define varying out #define texture2D texture `; const glsl300FragPrefixCommon = ` #define varying in #define texture2D texture #define textureCube texture #define texture2DLodEXT textureLod #define textureCubeLodEXT textureLod #define gl_FragColor out_FragData0 #define gl_FragDepthEXT gl_FragDepth `; function getGlsl300VertPrefix(extensions, shaderExtensions) { const prefix = [ '#version 300 es', ]; if (shaderExtensions.drawBuffers) { if (extensions.drawBuffers) { prefix.push('#define requiredDrawBuffers'); } } if (shaderExtensions.multiDraw) { if (extensions.multiDraw) { prefix.push('#extension GL_ANGLE_multi_draw : require'); prefix.push('#define enabledMultiDraw'); } else if (shaderExtensions.multiDraw === 'required') { throw new Error(`required 'GL_ANGLE_multi_draw' extension not available`); } } if (shaderExtensions.clipCullDistance) { if (extensions.clipCullDistance) { prefix.push('#extension GL_ANGLE_clip_cull_distance : enable'); prefix.push('#define enabledClipCullDistance'); } else if (shaderExtensions.clipCullDistance === 'required') { throw new Error(`required 'GL_ANGLE_clip_cull_distance' extension not available`); } } if (shaderExtensions.conservativeDepth) { if (extensions.conservativeDepth) { prefix.push('#extension GL_EXT_conservative_depth : enable'); prefix.push('#define enabledConservativeDepth'); } else if (shaderExtensions.conservativeDepth === 'required') { throw new Error(`required 'GL_EXT_conservative_depth' extension not available`); } } if (extensions.noNonInstancedActiveAttribs) { prefix.push('#define noNonInstancedActiveAttribs'); } prefix.push(glsl300VertPrefixCommon); return prefix.join('\n') + '\n'; } function getGlsl300FragPrefix(gl, extensions, shaderExtensions, outTypes) { const prefix = [ '#version 300 es', `layout(location = 0) out highp ${outTypes[0] || 'vec4'} out_FragData0;` ]; if (shaderExtensions.fragDepth) { if (extensions.fragDepth) { prefix.push('#define enabledFragDepth'); } } if (shaderExtensions.drawBuffers) { if (extensions.drawBuffers) { prefix.push('#define requiredDrawBuffers'); const maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS); for (let i = 1, il = maxDrawBuffers; i < il; ++i) { prefix.push(`layout(location = ${i}) out highp ${outTypes[i] || 'vec4'} out_FragData${i};`); } } } if (shaderExtensions.shaderTextureLod) { if (extensions.shaderTextureLod) { prefix.push('#define enabledShaderTextureLod'); } } if (extensions.depthTexture) { prefix.push('#define depthTextureSupport'); } prefix.push(glsl300FragPrefixCommon); return prefix.join('\n') + '\n'; } function transformGlsl300Frag(frag) { return frag.replace(/gl_FragData\[([0-9]+)\]/g, 'out_FragData$1'); } function addShaderDefines(gl, extensions, defines, shaders) { const vertHeader = getDefinesCode(defines, shaders.ignoreDefine); const fragHeader = getDefinesCode(defines, shaders.ignoreDefine); const vertPrefix = (0, compat_1.isWebGL2)(gl) ? getGlsl300VertPrefix(extensions, shaders.extensions) : getGlsl100VertPrefix(extensions, shaders.extensions); const fragPrefix = (0, compat_1.isWebGL2)(gl) ? getGlsl300FragPrefix(gl, extensions, shaders.extensions, shaders.outTypes) : getGlsl100FragPrefix(extensions, shaders.extensions); const frag = (0, compat_1.isWebGL2)(gl) ? transformGlsl300Frag(shaders.frag) : shaders.frag; return { id: shaderCodeId(), name: shaders.name, vert: `${vertPrefix}${vertHeader}${preprocess(shaders.vert, defines)}`, frag: `${fragPrefix}${fragHeader}${preprocess(frag, defines)}`, extensions: shaders.extensions, outTypes: shaders.outTypes }; }