diff --git a/src/mol-gl/shader-code.ts b/src/mol-gl/shader-code.ts index 26d8011827fadb8641fa83f2e1a7badeeaa47f6f..097d5bbd458e6db563e0872050c85e66ff49636c 100644 --- a/src/mol-gl/shader-code.ts +++ b/src/mol-gl/shader-code.ts @@ -14,39 +14,50 @@ export type DefineValues = { [k: string]: ValueCell<DefineType> } const shaderCodeId = idFactory() +export interface ShaderExtensions { + readonly standardDerivatives: boolean + readonly fragDepth: boolean +} + export interface ShaderCode { - id: number - vert: string - frag: string + readonly id: number + readonly vert: string + readonly frag: string + readonly extensions: ShaderExtensions } -export function ShaderCode(vert: string, frag: string): ShaderCode { - return { id: shaderCodeId(), vert, frag } +export function ShaderCode(vert: string, frag: string, extensions: ShaderExtensions): ShaderCode { + return { id: shaderCodeId(), vert, frag, extensions } } export const PointsShaderCode = ShaderCode( require('mol-gl/shader/points.vert'), - require('mol-gl/shader/points.frag') + require('mol-gl/shader/points.frag'), + { standardDerivatives: false, fragDepth: false } ) export const LinesShaderCode = ShaderCode( require('mol-gl/shader/lines.vert'), - require('mol-gl/shader/lines.frag') + require('mol-gl/shader/lines.frag'), + { standardDerivatives: false, fragDepth: false } ) export const MeshShaderCode = ShaderCode( require('mol-gl/shader/mesh.vert'), - require('mol-gl/shader/mesh.frag') + require('mol-gl/shader/mesh.frag'), + { standardDerivatives: true, fragDepth: false } ) export const GaussianDensityShaderCode = ShaderCode( require('mol-gl/shader/gaussian-density.vert'), - require('mol-gl/shader/gaussian-density.frag') + require('mol-gl/shader/gaussian-density.frag'), + { standardDerivatives: false, fragDepth: false } ) export const DirectVolumeShaderCode = ShaderCode( require('mol-gl/shader/direct-volume.vert'), - require('mol-gl/shader/direct-volume.frag') + require('mol-gl/shader/direct-volume.frag'), + { standardDerivatives: false, fragDepth: true } ) export type ShaderDefines = { @@ -74,8 +85,20 @@ function getDefinesCode (defines: ShaderDefines) { return lines.join('\n') + '\n' } -const glsl100FragPrefix = `#extension GL_OES_standard_derivatives : enable -` +function getGlsl100FragPrefix(ctx: Context, extensions: ShaderExtensions) { + const prefix: string[] = [] + if (extensions.standardDerivatives) { + prefix.push('#extension GL_OES_standard_derivatives : enable') + prefix.push('#define enabledStandardDerivatives') + } + if (extensions.fragDepth) { + if (ctx.extensions.fragDepth) { + prefix.push('#extension GL_EXT_frag_depth : enable') + prefix.push('#define enabledFragDepth') + } + } + return prefix.join('\n') + '\n' +} const glsl300VertPrefix = `#version 300 es #define attribute in @@ -89,16 +112,20 @@ layout(location = 0) out highp vec4 out_FragColor; #define gl_FragColor out_FragColor #define gl_FragDepthEXT gl_FragDepth #define texture2D texture + +#define enabledStandardDerivatives +#define enabledFragDepth ` export function addShaderDefines(ctx: Context, defines: ShaderDefines, shaders: ShaderCode): ShaderCode { const { isWebGL2 } = ctx const header = getDefinesCode(defines) const vertPrefix = isWebGL2 ? glsl300VertPrefix : '' - const fragPrefix = isWebGL2 ? glsl300FragPrefix : glsl100FragPrefix + const fragPrefix = isWebGL2 ? glsl300FragPrefix : getGlsl100FragPrefix(ctx, shaders.extensions) return { id: shaderCodeId(), vert: `${vertPrefix}${header}${shaders.vert}`, - frag: `${fragPrefix}${header}${shaders.frag}` + frag: `${fragPrefix}${header}${shaders.frag}`, + extensions: shaders.extensions } } \ No newline at end of file diff --git a/src/mol-gl/webgl/compat.ts b/src/mol-gl/webgl/compat.ts index 9fbaba5956960411ab9f14dab57e411db02a3143..7d763614ea33e22cf2c1c5ec32b8d5b85fb64ce2 100644 --- a/src/mol-gl/webgl/compat.ts +++ b/src/mol-gl/webgl/compat.ts @@ -121,4 +121,11 @@ export function getBlendMinMax(gl: GLRenderingContext): COMPAT_blend_minmax | nu if (ext === null) return null return { MIN: ext.MIN_EXT, MAX: ext.MAX_EXT } } +} + +export interface COMPAT_frag_depth { +} + +export function getFragDepth(gl: GLRenderingContext): COMPAT_frag_depth | null { + return isWebGL2(gl) ? {} : gl.getExtension('EXT_frag_depth') } \ No newline at end of file diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts index 3fd9a2e3fa7e1c67af3fd8c39f62ef140f7bc7ac..93924a73f7ee88ff24895b4c27d603cd45728dee 100644 --- a/src/mol-gl/webgl/context.ts +++ b/src/mol-gl/webgl/context.ts @@ -6,7 +6,7 @@ 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, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax } from './compat'; +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 } from './compat'; export function getGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes): GLRenderingContext | null { function getContext(contextId: 'webgl' | 'experimental-webgl' | 'webgl2') { @@ -105,6 +105,7 @@ type Extensions = { textureFloatLinear: COMPAT_texture_float_linear elementIndexUint: COMPAT_element_index_uint | null vertexArrayObject: COMPAT_vertex_array_object | null + fragDepth: COMPAT_frag_depth | null } /** A WebGL context object, including the rendering context, resource caches and counts */ @@ -165,6 +166,10 @@ export function createContext(gl: GLRenderingContext): Context { 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 shaderCache = createShaderCache() const programCache = createProgramCache() @@ -172,6 +177,11 @@ export function createContext(gl: GLRenderingContext): Context { const parameters = { maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE), maxDrawBuffers: isWebGL2(gl) ? gl.getParameter(gl.MAX_DRAW_BUFFERS) : 0, + maxVertexTextureImageUnits: gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS), + } + + if (parameters.maxVertexTextureImageUnits < 4) { + throw new Error('Need "MAX_VERTEX_TEXTURE_IMAGE_UNITS" >= 4') } return { @@ -184,7 +194,8 @@ export function createContext(gl: GLRenderingContext): Context { textureFloat, textureFloatLinear, elementIndexUint, - vertexArrayObject + vertexArrayObject, + fragDepth }, pixelRatio: getPixelRatio(),