Parcourir la source

add support for webgl extensions

- EXT_conservative_depth
- WEBGL_stencil_texturing
- EXT_clip_control
Alexander Rose il y a 1 an
Parent
commit
c427549b8d

+ 5 - 1
CHANGELOG.md

@@ -11,7 +11,11 @@ Note that since we don't clearly distinguish between a public and private interf
 - ModelServer ligand queries: fix atom count reported by SDF/MOL/MOL2 export
 - CCD extension: Make visuals for aromatic bonds configurable
 - Add optional `file?: CifFile` to `MmcifFormat.data`
-- Add support for `WEBGL_clip_cull_distance`
+- Add support for webgl extensions
+    - `WEBGL_clip_cull_distance`
+    - `EXT_conservative_depth`
+    - `WEBGL_stencil_texturing`
+    - `EXT_clip_control`
 - Add `MultiSampleParams.reduceFlicker` (to be able to switch it off)
 - Add `alphaThickness` parameter to adjust alpha of spheres for radius
 

+ 13 - 3
src/mol-gl/shader-code.ts

@@ -8,6 +8,7 @@ import { ValueCell } from '../mol-util';
 import { idFactory } from '../mol-util/id-factory';
 import { WebGLExtensions } from './webgl/extensions';
 import { isWebGL2, GLRenderingContext } from './webgl/compat';
+import { assertUnreachable } from '../mol-util/type-helpers';
 
 export type DefineKind = 'boolean' | 'string' | 'number'
 export type DefineType = boolean | string
@@ -21,6 +22,7 @@ export interface ShaderExtensions {
     readonly drawBuffers?: ShaderExtensionsValue
     readonly shaderTextureLod?: ShaderExtensionsValue
     readonly clipCullDistance?: ShaderExtensionsValue
+    readonly conservativeDepth?: ShaderExtensionsValue
 }
 
 type FragOutTypes = { [k in number]: 'vec4' | 'ivec4' }
@@ -128,7 +130,7 @@ function unrollLoops(str: string) {
     return str.replace(reUnrollLoop, loopReplacer);
 }
 
-function loopReplacer(match: string, start: string, end: string, snippet: string) {
+function loopReplacer(_match: string, start: string, end: string, snippet: string) {
     let out = '';
     for (let i = parseInt(start); i < parseInt(end); ++i) {
         out += snippet
@@ -162,9 +164,10 @@ function ignoreDefine(name: string, variant: string, defines: ShaderDefines): bo
     } else {
         return [
             'dColorType', 'dUsePalette',
-            'dLightCount',
+            'dLightCount', 'dXrayShaded',
             'dOverpaintType', 'dOverpaint',
             'dSubstanceType', 'dSubstance',
+            'dColorMarker',
         ].includes(name);
     }
     return false;
@@ -205,7 +208,6 @@ export const DirectVolumeShaderCode = ShaderCode('direct-volume', directVolume_v
 
 import { image_vert } from './shader/image.vert';
 import { image_frag } from './shader/image.frag';
-import { assertUnreachable } from '../mol-util/type-helpers';
 export const ImageShaderCode = ShaderCode('image', image_vert, image_frag, { drawBuffers: 'optional' }, {}, ignoreDefineUnlit);
 
 //
@@ -322,6 +324,14 @@ function getGlsl300VertPrefix(extensions: WebGLExtensions, shaderExtensions: Sha
             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');
     }

+ 76 - 0
src/mol-gl/webgl/compat.ts

@@ -627,6 +627,82 @@ export function getClipCullDistance(gl: GLRenderingContext): COMPAT_clip_cull_di
     return null;
 }
 
+/**
+ * See https://registry.khronos.org/webgl/extensions/EXT_conservative_depth/
+ */
+export interface COMPAT_conservative_depth {
+}
+
+export function getConservativeDepth(gl: GLRenderingContext): COMPAT_conservative_depth | null {
+    if (isWebGL2(gl)) {
+        const ext = gl.getExtension('EXT_conservative_depth');
+        if (ext) {
+            return {};
+        }
+    }
+    return null;
+}
+
+/**
+ * See https://registry.khronos.org/webgl/extensions/WEBGL_stencil_texturing/
+ */
+export interface COMPAT_stencil_texturing {
+    readonly DEPTH_STENCIL_TEXTURE_MODE: number;
+    readonly STENCIL_INDEX: number;
+}
+
+export function getStencilTexturing(gl: GLRenderingContext): COMPAT_stencil_texturing | null {
+    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;
+}
+
+/**
+ * See https://registry.khronos.org/webgl/extensions/EXT_clip_control/
+ */
+export interface COMPAT_clip_control {
+    readonly LOWER_LEFT: number;
+    readonly UPPER_LEFT: number;
+
+    readonly NEGATIVE_ONE_TO_ONE: number;
+    readonly ZERO_TO_ONE: number;
+
+    readonly CLIP_ORIGIN: number;
+    readonly CLIP_DEPTH_MODE: number;
+
+    /**
+     * @param origin must be LOWER_LEFT (default) or UPPER_LEFT.
+     * @param depth must be NEGATIVE_ONE_TO_ONE (default) or ZERO_TO_ONE.
+     */
+    clipControl(origin: number, depth: number): void
+}
+
+export function getClipControl(gl: GLRenderingContext): COMPAT_clip_control | null {
+    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;
+}
+
 export function getNoNonInstancedActiveAttribs(gl: GLRenderingContext): boolean {
     if (!isWebGL2(gl)) return false;
 

+ 1 - 1
src/mol-gl/webgl/context.ts

@@ -237,7 +237,7 @@ export interface WebGLContext {
 
 export function createContext(gl: GLRenderingContext, props: Partial<{ pixelScale: number }> = {}): WebGLContext {
     const extensions = createExtensions(gl);
-    const state = createState(gl);
+    const state = createState(gl, extensions);
     const stats = createStats();
     const resources = createResources(gl, state, stats, extensions);
     const timer = createTimer(gl, extensions, stats);

+ 19 - 1
src/mol-gl/webgl/extensions.ts

@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs, getDrawBuffersIndexed, COMPAT_draw_buffers_indexed, getParallelShaderCompile, COMPAT_parallel_shader_compile, getFboRenderMipmap, COMPAT_fboRenderMipmap, COMPAT_provoking_vertex, getProvokingVertex, COMPAT_clip_cull_distance, getClipCullDistance } from './compat';
+import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs, getDrawBuffersIndexed, COMPAT_draw_buffers_indexed, getParallelShaderCompile, COMPAT_parallel_shader_compile, getFboRenderMipmap, COMPAT_fboRenderMipmap, COMPAT_provoking_vertex, getProvokingVertex, COMPAT_clip_cull_distance, getClipCullDistance, COMPAT_conservative_depth, getConservativeDepth, COMPAT_stencil_texturing, getStencilTexturing, COMPAT_clip_control, getClipControl } from './compat';
 import { isDebugMode } from '../../mol-util/debug';
 
 export type WebGLExtensions = {
@@ -31,6 +31,9 @@ export type WebGLExtensions = {
     fboRenderMipmap: COMPAT_fboRenderMipmap | null
     provokingVertex: COMPAT_provoking_vertex | null
     clipCullDistance: COMPAT_clip_cull_distance | null
+    conservativeDepth: COMPAT_conservative_depth | null
+    stencilTexturing: COMPAT_stencil_texturing | null
+    clipControl: COMPAT_clip_control | null
 
     noNonInstancedActiveAttribs: boolean
 }
@@ -131,6 +134,18 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
     if (isDebugMode && clipCullDistance === null) {
         console.log('Could not find support for "clip_cull_distance"');
     }
+    const conservativeDepth = getConservativeDepth(gl);
+    if (isDebugMode && conservativeDepth === null) {
+        console.log('Could not find support for "conservative_depth"');
+    }
+    const stencilTexturing = getStencilTexturing(gl);
+    if (isDebugMode && stencilTexturing === null) {
+        console.log('Could not find support for "stencil_texturing"');
+    }
+    const clipControl = getClipControl(gl);
+    if (isDebugMode && clipControl === null) {
+        console.log('Could not find support for "clipControl"');
+    }
 
     const noNonInstancedActiveAttribs = getNoNonInstancedActiveAttribs(gl);
 
@@ -158,6 +173,9 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
         fboRenderMipmap,
         provokingVertex,
         clipCullDistance,
+        conservativeDepth,
+        stencilTexturing,
+        clipControl,
 
         noNonInstancedActiveAttribs,
     };

+ 24 - 1
src/mol-gl/webgl/state.ts

@@ -5,6 +5,7 @@
  */
 
 import { GLRenderingContext } from './compat';
+import { WebGLExtensions } from './extensions';
 
 export type WebGLState = {
     currentProgramId: number
@@ -87,10 +88,18 @@ export type WebGLState = {
     viewport: (x: number, y: number, width: number, height: number) => void
     scissor: (x: number, y: number, width: number, height: number) => void
 
+    /**
+     * controls the clipping volume behavior
+     * @param origin must be `ext.LOWER_LEFT` (default) or `ext.UPPER_LEFT`.
+     * @param depth must be `ext.NEGATIVE_ONE_TO_ONE` (default) or `ext.ZERO_TO_ONE`.
+     * with `ext` being `EXT_clip_control`
+     */
+    clipControl?: (origin: number, depth: number) => void
+
     reset: () => void
 }
 
-export function createState(gl: GLRenderingContext): WebGLState {
+export function createState(gl: GLRenderingContext, e: WebGLExtensions): WebGLState {
     let enabledCapabilities: Record<number, boolean> = {};
 
     let currentFrontFace = gl.getParameter(gl.FRONT_FACE);
@@ -130,6 +139,9 @@ export function createState(gl: GLRenderingContext): WebGLState {
     let currentViewport: [number, number, number, number] = gl.getParameter(gl.VIEWPORT);
     let currentScissor: [number, number, number, number] = gl.getParameter(gl.SCISSOR_BOX);
 
+    let currentClipOrigin = e.clipControl ? gl.getParameter(e.clipControl.CLIP_ORIGIN) : -1;
+    let currentClipDepthMode = e.clipControl ? gl.getParameter(e.clipControl.CLIP_DEPTH_MODE) : -1;
+
     const clearVertexAttribsState = () => {
         for (let i = 0; i < maxVertexAttribs; ++i) {
             vertexAttribsState[i] = 0;
@@ -380,6 +392,14 @@ export function createState(gl: GLRenderingContext): WebGLState {
             }
         },
 
+        clipControl: e.clipControl ? (origin: number, depth: number) => {
+            if (origin !== currentClipOrigin || depth !== currentClipDepthMode) {
+                e.clipControl!.clipControl(origin, depth);
+                currentClipOrigin = origin;
+                currentClipDepthMode = depth;
+            }
+        } : undefined,
+
         reset: () => {
             enabledCapabilities = {};
 
@@ -422,6 +442,9 @@ export function createState(gl: GLRenderingContext): WebGLState {
 
             currentViewport = gl.getParameter(gl.VIEWPORT);
             currentScissor = gl.getParameter(gl.SCISSOR_BOX);
+
+            currentClipOrigin = e.clipControl ? gl.getParameter(e.clipControl.CLIP_ORIGIN) : -1;
+            currentClipDepthMode = e.clipControl ? gl.getParameter(e.clipControl.CLIP_DEPTH_MODE) : -1;
         }
     };
 }