Pārlūkot izejas kodu

use pixel-size for max depth difference

Alexander Rose 2 gadi atpakaļ
vecāks
revīzija
7ea47d2a99

+ 13 - 28
src/mol-canvas3d/passes/postprocessing.ts

@@ -43,9 +43,9 @@ const OutlinesSchema = {
     dOrthographic: DefineSpec('number'),
     uNear: UniformSpec('f'),
     uFar: UniformSpec('f'),
+    uInvProjection: UniformSpec('m4'),
 
-    uMaxPossibleViewZDiff: UniformSpec('f'),
-
+    uOutlineThreshold: UniformSpec('f'),
     dTransparentOutline: DefineSpec('boolean'),
 };
 type OutlinesRenderable = ComputeRenderable<Values<typeof OutlinesSchema>>
@@ -63,9 +63,9 @@ function getOutlinesRenderable(ctx: WebGLContext, depthTextureOpaque: Texture, d
         dOrthographic: ValueCell.create(0),
         uNear: ValueCell.create(1),
         uFar: ValueCell.create(10000),
+        uInvProjection: ValueCell.create(Mat4.identity()),
 
-        uMaxPossibleViewZDiff: ValueCell.create(0.5),
-
+        uOutlineThreshold: ValueCell.create(0.33),
         dTransparentOutline: ValueCell.create(transparentOutline),
     };
 
@@ -189,8 +189,7 @@ const SsaoBlurSchema = {
     uBlurDirectionX: UniformSpec('f'),
     uBlurDirectionY: UniformSpec('f'),
 
-    uMaxPossibleViewZDiff: UniformSpec('f'),
-
+    uInvProjection: UniformSpec('m4'),
     uNear: UniformSpec('f'),
     uFar: UniformSpec('f'),
     uBounds: UniformSpec('v4'),
@@ -211,8 +210,7 @@ function getSsaoBlurRenderable(ctx: WebGLContext, ssaoDepthTexture: Texture, dir
         uBlurDirectionX: ValueCell.create(direction === 'horizontal' ? 1 : 0),
         uBlurDirectionY: ValueCell.create(direction === 'vertical' ? 1 : 0),
 
-        uMaxPossibleViewZDiff: ValueCell.create(0.5),
-
+        uInvProjection: ValueCell.create(Mat4.identity()),
         uNear: ValueCell.create(0.0),
         uFar: ValueCell.create(10000.0),
         uBounds: ValueCell.create(Vec4()),
@@ -283,9 +281,6 @@ const PostprocessingSchema = {
     uOcclusionColor: UniformSpec('v3'),
     uTransparentBackground: UniformSpec('b'),
 
-    uMaxPossibleViewZDiff: UniformSpec('f'),
-    uInvProjection: UniformSpec('m4'),
-
     dOcclusionEnable: DefineSpec('boolean'),
     uOcclusionOffset: UniformSpec('v2'),
 
@@ -293,8 +288,6 @@ const PostprocessingSchema = {
 
     dOutlineEnable: DefineSpec('boolean'),
     dOutlineScale: DefineSpec('number'),
-    uOutlineThreshold: UniformSpec('f'),
-
     dTransparentOutline: DefineSpec('boolean'),
 };
 type PostprocessingRenderable = ComputeRenderable<Values<typeof PostprocessingSchema>>
@@ -321,9 +314,6 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
         uOcclusionColor: ValueCell.create(Vec3.create(0, 0, 0)),
         uTransparentBackground: ValueCell.create(false),
 
-        uMaxPossibleViewZDiff: ValueCell.create(0.5),
-        uInvProjection: ValueCell.create(Mat4.identity()),
-
         dOcclusionEnable: ValueCell.create(true),
         uOcclusionOffset: ValueCell.create(Vec2.create(0, 0)),
 
@@ -331,8 +321,6 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
 
         dOutlineEnable: ValueCell.create(false),
         dOutlineScale: ValueCell.create(1),
-        uOutlineThreshold: ValueCell.create(0.33),
-
         dTransparentOutline: ValueCell.create(transparentOutline),
     };
 
@@ -546,6 +534,9 @@ export class PostprocessingPass {
             ValueCell.updateIfChanged(this.ssaoBlurFirstPassRenderable.values.uFar, camera.far);
             ValueCell.updateIfChanged(this.ssaoBlurSecondPassRenderable.values.uFar, camera.far);
 
+            ValueCell.update(this.ssaoBlurFirstPassRenderable.values.uInvProjection, invProjection);
+            ValueCell.update(this.ssaoBlurSecondPassRenderable.values.uInvProjection, invProjection);
+
             if (this.ssaoBlurFirstPassRenderable.values.dOrthographic.ref.value !== orthographic) {
                 needsUpdateSsaoBlur = true;
                 ValueCell.update(this.ssaoBlurFirstPassRenderable.values.dOrthographic, orthographic);
@@ -638,17 +629,13 @@ export class PostprocessingPass {
         }
 
         if (props.outline.name === 'on') {
-            let { threshold, includeTransparent } = props.outline.params;
-            const transparentOutline = includeTransparent ?? true;
-            // orthographic needs lower threshold
-            if (camera.state.mode === 'orthographic') threshold /= 5;
-            const factor = Math.pow(1000, threshold / 10) / 1000;
-            // use radiusMax for stable outlines when zooming
-            const maxPossibleViewZDiff = factor * camera.state.radiusMax;
+            const transparentOutline = props.outline.params.includeTransparent ?? true;
             const outlineScale = props.outline.params.scale - 1;
+            const outlineThreshold = 50 * props.outline.params.threshold;
 
             ValueCell.updateIfChanged(this.outlinesRenderable.values.uNear, camera.near);
             ValueCell.updateIfChanged(this.outlinesRenderable.values.uFar, camera.far);
+            ValueCell.update(this.outlinesRenderable.values.uInvProjection, invProjection);
             if (this.outlinesRenderable.values.dTransparentOutline.ref.value !== transparentOutline) {
                 needsUpdateOutlines = true;
                 ValueCell.update(this.outlinesRenderable.values.dTransparentOutline, transparentOutline);
@@ -657,12 +644,10 @@ export class PostprocessingPass {
                 needsUpdateOutlines = true;
                 ValueCell.update(this.outlinesRenderable.values.dOrthographic, orthographic);
             }
+            ValueCell.updateIfChanged(this.outlinesRenderable.values.uOutlineThreshold, outlineThreshold);
 
             ValueCell.update(this.renderable.values.uOutlineColor, Color.toVec3Normalized(this.renderable.values.uOutlineColor.ref.value, props.outline.params.color));
 
-            ValueCell.updateIfChanged(this.renderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff);
-            ValueCell.update(this.renderable.values.uInvProjection, invProjection);
-
             if (this.renderable.values.dOutlineScale.ref.value !== outlineScale) {
                 needsUpdateMain = true;
                 ValueCell.update(this.renderable.values.dOutlineScale, outlineScale);

+ 13 - 4
src/mol-gl/shader/outlines.frag.ts

@@ -16,8 +16,9 @@ uniform vec2 uTexSize;
 
 uniform float uNear;
 uniform float uFar;
+uniform mat4 uInvProjection;
 
-uniform float uMaxPossibleViewZDiff;
+uniform float uOutlineThreshold;
 
 #include common
 
@@ -49,17 +50,25 @@ bool isBackground(const in float depth) {
     return depth == 1.0;
 }
 
+float getPixelSize(const in vec2 coords, const in float depth) {
+    vec3 viewPos0 = screenSpaceToViewSpace(vec3(coords, depth), uInvProjection);
+    vec3 viewPos1 = screenSpaceToViewSpace(vec3(coords + vec2(1.0, 0.0) / uTexSize, depth), uInvProjection);
+    return distance(viewPos0, viewPos1);
+}
+
 void main(void) {
-    float backgroundViewZ = uFar + 3.0 * uMaxPossibleViewZDiff;
+    float backgroundViewZ = 2.0 * uFar;
 
     vec2 coords = gl_FragCoord.xy / uTexSize;
     vec2 invTexSize = 1.0 / uTexSize;
 
     float selfDepthOpaque = getDepthOpaque(coords);
     float selfViewZOpaque = isBackground(selfDepthOpaque) ? backgroundViewZ : getViewZ(selfDepthOpaque);
+    float pixelSizeOpaque = getPixelSize(coords, selfDepthOpaque) * uOutlineThreshold;
 
     float selfDepthTransparent = getDepthTransparent(coords);
     float selfViewZTransparent = isBackground(selfDepthTransparent) ? backgroundViewZ : getViewZ(selfDepthTransparent);
+    float pixelSizeTransparent = getPixelSize(coords, selfDepthTransparent) * uOutlineThreshold;
 
     float outline = 1.0;
     float bestDepth = 1.0;
@@ -73,14 +82,14 @@ void main(void) {
             float sampleDepthTransparent = getDepthTransparent(sampleCoords);
 
             float sampleViewZOpaque = isBackground(sampleDepthOpaque) ? backgroundViewZ : getViewZ(sampleDepthOpaque);
-            if (abs(selfViewZOpaque - sampleViewZOpaque) > uMaxPossibleViewZDiff && selfDepthOpaque > sampleDepthOpaque && sampleDepthOpaque <= bestDepth) {
+            if (abs(selfViewZOpaque - sampleViewZOpaque) > pixelSizeOpaque && selfDepthOpaque > sampleDepthOpaque && sampleDepthOpaque <= bestDepth) {
                 outline = 0.0;
                 bestDepth = sampleDepthOpaque;
             }
 
             if (sampleDepthTransparent < sampleDepthOpaque) {
                 float sampleViewZTransparent = isBackground(sampleDepthTransparent) ? backgroundViewZ : getViewZ(sampleDepthTransparent);
-                if (abs(selfViewZTransparent - sampleViewZTransparent) > uMaxPossibleViewZDiff && selfDepthTransparent > sampleDepthTransparent && sampleDepthTransparent <= bestDepth) {
+                if (abs(selfViewZTransparent - sampleViewZTransparent) > pixelSizeTransparent && selfDepthTransparent > sampleDepthTransparent && sampleDepthTransparent <= bestDepth) {
                     outline = 0.0;
                     bestDepth = sampleDepthTransparent;
                     transparentFlag = 1.0;

+ 2 - 14
src/mol-gl/shader/postprocessing.frag.ts

@@ -26,13 +26,8 @@ uniform vec3 uFogColor;
 uniform vec3 uOutlineColor;
 uniform vec3 uOcclusionColor;
 uniform bool uTransparentBackground;
-
 uniform vec2 uOcclusionOffset;
 
-uniform float uMaxPossibleViewZDiff;
-uniform mat4 uInvProjection;
-
-const float outlineDistanceFactor = 5.0;
 #include common
 
 float getViewZ(const in float depth) {
@@ -63,21 +58,14 @@ bool isBackground(const in float depth) {
     return depth == 1.0;
 }
 
-float getPixelSize(const in vec2 coords, const in float depth) {
-    vec3 viewPos0 = screenSpaceToViewSpace(vec3(coords, depth), uInvProjection);
-    vec3 viewPos1 = screenSpaceToViewSpace(vec3(coords + vec2(1.0, 0.0) / uTexSize, depth), uInvProjection);
-    return distance(viewPos0, viewPos1);
-}
-
 float getOutline(const in vec2 coords, const in float opaqueDepth, out float closestTexel) {
-    float backgroundViewZ = uFar + 3.0 * uMaxPossibleViewZDiff;
+    float backgroundViewZ = 2.0 * uFar;
     vec2 invTexSize = 1.0 / uTexSize;
 
     float transparentDepth = getDepthTransparent(coords);
     float opaqueSelfViewZ = isBackground(opaqueDepth) ? backgroundViewZ : getViewZ(opaqueDepth);
     float transparentSelfViewZ = isBackground(transparentDepth) ? backgroundViewZ : getViewZ(transparentDepth);
     float selfDepth = min(opaqueDepth, transparentDepth);
-    float pixelSize = getPixelSize(coords, selfDepth);
 
     float outline = 1.0;
     closestTexel = 1.0;
@@ -95,7 +83,7 @@ float getOutline(const in vec2 coords, const in float opaqueDepth, out float clo
             float sampleOutlineViewZ = isBackground(sampleOutlineDepth) ? backgroundViewZ : getViewZ(sampleOutlineDepth);
 
             float selfViewZ = sampleOutlineCombined.a == 0.0 ? opaqueSelfViewZ : transparentSelfViewZ;
-            if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel && abs(selfViewZ - sampleOutlineViewZ) > uMaxPossibleViewZDiff + (pixelSize * outlineDistanceFactor)) {
+            if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel) {
                 outline = 0.0;
                 closestTexel = sampleOutlineDepth;
             }

+ 11 - 4
src/mol-gl/shader/ssao-blur.frag.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -19,8 +19,7 @@ uniform float uKernel[dOcclusionKernelSize];
 uniform float uBlurDirectionX;
 uniform float uBlurDirectionY;
 
-uniform float uMaxPossibleViewZDiff;
-
+uniform mat4 uInvProjection;
 uniform float uNear;
 uniform float uFar;
 
@@ -42,6 +41,12 @@ bool outsideBounds(const in vec2 p) {
     return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w;
 }
 
+float getPixelSize(const in vec2 coords, const in float depth) {
+    vec3 viewPos0 = screenSpaceToViewSpace(vec3(coords, depth), uInvProjection);
+    vec3 viewPos1 = screenSpaceToViewSpace(vec3(coords + vec2(1.0, 0.0) / uTexSize, depth), uInvProjection);
+    return distance(viewPos0, viewPos1);
+}
+
 void main(void) {
     vec2 coords = gl_FragCoord.xy / uTexSize;
 
@@ -60,6 +65,8 @@ void main(void) {
     }
 
     float selfViewZ = getViewZ(selfDepth);
+    float pixelSize = getPixelSize(coords, selfDepth);
+    float maxDiffViewZ = pixelSize * 5.0;
 
     vec2 offset = vec2(uBlurDirectionX, uBlurDirectionY) / uTexSize;
 
@@ -81,7 +88,7 @@ void main(void) {
 
         if (abs(float(i)) > 1.0) { // abs is not defined for int in webgl1
             float sampleViewZ = getViewZ(sampleDepth);
-            if (abs(selfViewZ - sampleViewZ) > uMaxPossibleViewZDiff) {
+            if (abs(selfViewZ - sampleViewZ) > maxDiffViewZ) {
                 continue;
             }
         }