diff --git a/src/mol-canvas3d/passes/draw.ts b/src/mol-canvas3d/passes/draw.ts index 34282e8408d16a0c59251178c6ab14843914d707..00dd3b4a76e20d29780fda5d1b8053a7bf781dd9 100644 --- a/src/mol-canvas3d/passes/draw.ts +++ b/src/mol-canvas3d/passes/draw.ts @@ -145,6 +145,7 @@ export class DrawPass { if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) { this.depthTargetTransparent.bind(); renderer.clearDepth(true); + renderer.setOutlineAlphaThreshold(PostprocessingPass.getOutlineMinimumOpacity(postprocessingProps)); if (scene.opacityAverage < 1) { renderer.renderDepthTransparent(scene.primitives, camera, this.depthTextureOpaque); } @@ -199,6 +200,7 @@ export class DrawPass { if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) { this.depthTargetTransparent.bind(); renderer.clearDepth(true); + renderer.setOutlineAlphaThreshold(PostprocessingPass.getOutlineMinimumOpacity(postprocessingProps)); if (scene.opacityAverage < 1) { renderer.renderDepthTransparent(scene.primitives, camera, this.depthTextureOpaque); } @@ -263,6 +265,7 @@ export class DrawPass { if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) { this.depthTargetTransparent.bind(); renderer.clearDepth(true); + renderer.setOutlineAlphaThreshold(PostprocessingPass.getOutlineMinimumOpacity(postprocessingProps)); if (scene.opacityAverage < 1) { renderer.renderDepthTransparent(scene.primitives, camera, this.depthTextureOpaque); } diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index 591517976863a47013460eb3158cfeeb699619a4..febf0e4272a166ec68d3e936e3a9656310ee769e 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -279,6 +279,7 @@ export const PostprocessingParams = { scale: PD.Numeric(1, { min: 1, max: 5, step: 1 }), threshold: PD.Numeric(0.33, { min: 0.01, max: 1, step: 0.01 }), color: PD.Color(Color(0x000000)), + minimumOpacity: PD.Optional(PD.Numeric(0.0, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be have an outline'})), }), off: PD.Group({}) }, { cycle: true, description: 'Draw outline around 3D objects' }), @@ -300,6 +301,10 @@ export class PostprocessingPass { return props.outline.name === 'on'; } + static getOutlineMinimumOpacity(props: PostprocessingProps) { + return props.outline.name === 'on' ? props.outline.params.minimumOpacity ?? 0.0 : 0.0 + } + readonly target: RenderTarget; private readonly outlinesTarget: RenderTarget; diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 086f6db4086bed82767ccb56c8d8bb7bec60f58a..ab65486008c0dccbbe3ae2df624573cdba437d0e 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -80,6 +80,7 @@ interface Renderer { setTransparentBackground: (value: boolean) => void setDrawingBufferSize: (width: number, height: number) => void setPixelRatio: (value: number) => void + setOutlineAlphaThreshold: (value: number) => void dispose: () => void } @@ -186,6 +187,8 @@ namespace Renderer { const ambientColor = Vec3(); Vec3.scale(ambientColor, Color.toArrayNormalized(p.ambientColor, ambientColor, 0), p.ambientIntensity); + let outlineAlphaThreshold = 0.0; + const globalUniforms: GlobalUniformValues = { uModel: ValueCell.create(Mat4.identity()), uView: ValueCell.create(view), @@ -432,7 +435,7 @@ namespace Renderer { const { renderables } = group; for (let i = 0, il = renderables.length; i < il; ++i) { const r = renderables[i]; - if (!r.state.opaque || r.values.transparencyAverage.ref.value > 0 || r.values.dXrayShaded?.ref.value) { + if ((!r.state.opaque && r.values.alpha.ref.value > outlineAlphaThreshold) || r.values.transparencyAverage.ref.value > 0 || r.values.dXrayShaded?.ref.value) { renderObject(r, 'depth', Flag.None); } } @@ -827,6 +830,9 @@ namespace Renderer { instancedDrawCount: stats.instancedDrawCount, }; }, + setOutlineAlphaThreshold: (value: number) => { + outlineAlphaThreshold = value; + }, dispose: () => { // TODO }