diff --git a/src/apps/docking-viewer/viewport.tsx b/src/apps/docking-viewer/viewport.tsx index 1642a5d0a739c6a12bfd12841d2219e84308168e..6e59f3c3d685c3b7c930e6ce31bf0532e52dc9d3 100644 --- a/src/apps/docking-viewer/viewport.tsx +++ b/src/apps/docking-viewer/viewport.tsx @@ -50,7 +50,8 @@ function occlusionStyle(plugin: PluginContext) { samples: 32, resolutionScale: 1, shadow: { name: 'off', params: {} }, - closeAO: { name: 'off', params: {} } + closeAO: { name: 'off', params: {} }, + softAO: { name: 'off', params: {} } } }, outline: { name: 'on', params: { scale: 1.0, diff --git a/src/examples/lighting/index.ts b/src/examples/lighting/index.ts index 657d149092694e76239a41c5141327145b54a564..287ca851c754dd964a2dc92baaabf0e26f047718 100644 --- a/src/examples/lighting/index.ts +++ b/src/examples/lighting/index.ts @@ -30,6 +30,7 @@ const Canvas3DPresets = { radius: 5, samples: 32, resolutionScale: 1, + softAO: { name: 'off', params: {} }, shadow: { name: 'off', params: {} }, closeAO: { name: 'off', params: {} } } }, @@ -50,6 +51,7 @@ const Canvas3DPresets = { radius: 5, samples: 32, resolutionScale: 1, + softAO: { name: 'off', params: {} }, shadow: { name: 'off', params: {} }, closeAO: { name: 'off', params: {} } } }, diff --git a/src/extensions/cellpack/model.ts b/src/extensions/cellpack/model.ts index e54ddb0c3ae8669b031eea7a6f21ede8ced96ad4..77c040b624464d272749754c1ef868f79734889e 100644 --- a/src/extensions/cellpack/model.ts +++ b/src/extensions/cellpack/model.ts @@ -605,6 +605,7 @@ export const LoadCellPackModel = StateAction.build({ blurKernelSize: 15, resolutionScale: 1, shadow: { name: 'off', params: {} }, + softAO: { name: 'off', params: {} }, closeAO: { name: 'off', params: {} } } }, diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index 3a25c03475f5ba518c15865fda96ad69988456c3..cf8e4916c3fa66912258d9896cb9a0be05c80392 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -92,12 +92,26 @@ const SsaoSchema = { uCloseBias: UniformSpec('f'), uCloseDistance: UniformSpec('f'), + uCDistanceCutoff: UniformSpec('f'), + uCCutoffFalloff: UniformSpec('f'), + uCIntensity: UniformSpec('f'), + uCDistance: UniformSpec('f'), + uShadow: UniformSpec('i'), dSSample: DefineSpec('number'), uSDistance: UniformSpec('f'), uSTolerance: UniformSpec('f'), uSBias: UniformSpec('f'), + uSoftAO: UniformSpec('i'), + uAorange: UniformSpec('f'), + uDepthTolerance: UniformSpec('f'), + uAoMultiplier: UniformSpec('f'), + uAoCap: UniformSpec('f'), + uAScale: UniformSpec('f'), + uARings: UniformSpec('i'), + uASamples: UniformSpec('i'), + uLightDirection: UniformSpec('v3[]'), uLightColor: UniformSpec('v3[]'), dLightCount: DefineSpec('number'), @@ -134,6 +148,10 @@ function getSsaoRenderable(ctx: WebGLContext, depthTexture: Texture): SsaoRender uCloseAO: ValueCell.create(1), uCloseBias: ValueCell.create(1.0), uCloseDistance: ValueCell.create(0.01), + uCDistanceCutoff: ValueCell.create(1.0), + uCCutoffFalloff: ValueCell.create(1.0), + uCIntensity: ValueCell.create(1.0), + uCDistance: ValueCell.create(1.0), uShadow: ValueCell.create(1), dSSample: ValueCell.create(1), @@ -141,6 +159,15 @@ function getSsaoRenderable(ctx: WebGLContext, depthTexture: Texture): SsaoRender uSTolerance: ValueCell.create(0.2), uSBias: ValueCell.create(1.5), + uSoftAO: ValueCell.create(1), + uAorange: ValueCell.create(1.0), + uDepthTolerance: ValueCell.create(1.0), + uAoMultiplier: ValueCell.create(1.0), + uAoCap: ValueCell.create(1.0), + uAScale: ValueCell.create(1.0), + uARings: ValueCell.create(1), + uASamples: ValueCell.create(1), + dOrthographic: ValueCell.create(0), uNear: ValueCell.create(0.0), uFar: ValueCell.create(10000.0), @@ -328,8 +355,24 @@ export const PostprocessingParams = { }, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }), closeAO: PD.MappedStatic('on', { on: PD.Group({ - cbias: PD.Numeric(1.0, { min: 0.0, max: 2.0, step: 0.01 }), - cdistance: PD.Numeric(0.015, { min: 0.0, max: 0.2, step: 0.001 }), + cbias: PD.Numeric(0.0, { min: 0.0, max: 1.0, step: 0.01 }), + cradius: PD.Numeric(0.015, { min: 0.0, max: 0.2, step: 0.001 }), + cdistancecutoff: PD.Numeric(2000.0, { min: 0.0, max: 10000.0, step: 1.0 }), + ccutofffalloff: PD.Numeric(25.0, { min: 0.0, max: 10000.0, step: 0.001 }), + cintensity: PD.Numeric(1.0, { min: 0.0, max: 1.0, step: 0.1 }), + cdistance: PD.Numeric(0.0015, { min: 0.0, max: 0.2, step: 0.001 }), + }), + off: PD.Group({}) + }, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }), + softAO: PD.MappedStatic('on', { + on: PD.Group({ + uAorange: PD.Numeric(160.0, { min: 0.0, max: 500.0, step: 1.0 }), + uDepthTolerance: PD.Numeric(0.0, { min: 0.0, max: 200.0, step: 0.01 }), + uAoMultiplier: PD.Numeric(100.0, { min: 0.0, max: 2000.0, step: 0.01 }), + uAoCap: PD.Numeric(1.0, { min: 0.0, max: 10.0, step: 0.01 }), + uAScale: PD.Numeric(1.0, { min: 0.0, max: 10.0, step: 0.01 }), + uARings: PD.Numeric(6.0, { min: 0.0, max: 10.0, step: 1 }), + uASamples: PD.Numeric(3.0, { min: 0.0, max: 10.0, step: 1 }), }), off: PD.Group({}) }, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }), @@ -477,16 +520,17 @@ export class PostprocessingPass { const orthographic = camera.state.mode === 'orthographic' ? 1 : 0; const outlinesEnabled = props.outline.name === 'on'; const occlusionEnabled = props.occlusion.name === 'on'; - const invProjection = Mat4.identity(); Mat4.invert(invProjection, camera.projection); if (props.occlusion.name === 'on') { const shadowocclusionEnabled = props.occlusion.params.shadow.name === 'on' ? 1 : 0; const closeocclusionEnabled = props.occlusion.params.closeAO.name === 'on' ? 1 : 0; + const softocclusionEnabled = props.occlusion.params.softAO.name === 'on' ? 1 : 0; ValueCell.update(this.ssaoRenderable.values.uShadow, shadowocclusionEnabled); ValueCell.update(this.ssaoRenderable.values.uCloseAO, closeocclusionEnabled); + ValueCell.update(this.ssaoRenderable.values.uSoftAO, softocclusionEnabled); ValueCell.update(this.ssaoRenderable.values.uProjection, camera.projection); ValueCell.update(this.ssaoRenderable.values.uInvProjection, invProjection); @@ -547,13 +591,31 @@ export class PostprocessingPass { if (props.occlusion.params.closeAO.name === 'on') { ValueCell.update(this.ssaoRenderable.values.uCloseBias, props.occlusion.params.closeAO.params.cbias); - ValueCell.update(this.ssaoRenderable.values.uCloseDistance, props.occlusion.params.closeAO.params.cdistance); + ValueCell.update(this.ssaoRenderable.values.uCloseDistance, props.occlusion.params.closeAO.params.cradius); + ValueCell.update(this.ssaoRenderable.values.uCDistanceCutoff, props.occlusion.params.closeAO.params.cdistancecutoff); + ValueCell.update(this.ssaoRenderable.values.uCCutoffFalloff, props.occlusion.params.closeAO.params.ccutofffalloff); + ValueCell.update(this.ssaoRenderable.values.uCIntensity, props.occlusion.params.closeAO.params.cintensity); + ValueCell.update(this.ssaoRenderable.values.uCDistance, props.occlusion.params.closeAO.params.cdistance); if (this.ssaoRenderable.values.uCloseBias.ref.value !== props.occlusion.params.closeAO.params.cbias || this.ssaoRenderable.values.uCloseDistance.ref.value !== props.occlusion.params.closeAO.params.cdistance) { needsUpdateSsao = true; } } + if (props.occlusion.params.softAO.name === 'on') { + ValueCell.update(this.ssaoRenderable.values.uAorange, props.occlusion.params.softAO.params.uAorange); + ValueCell.update(this.ssaoRenderable.values.uDepthTolerance, props.occlusion.params.softAO.params.uDepthTolerance); + ValueCell.update(this.ssaoRenderable.values.uAoMultiplier, props.occlusion.params.softAO.params.uAoMultiplier); + ValueCell.update(this.ssaoRenderable.values.uAoCap, props.occlusion.params.softAO.params.uAoCap); + ValueCell.update(this.ssaoRenderable.values.uAScale, props.occlusion.params.softAO.params.uAScale); + ValueCell.update(this.ssaoRenderable.values.uARings, props.occlusion.params.softAO.params.uARings); + ValueCell.update(this.ssaoRenderable.values.uASamples, props.occlusion.params.softAO.params.uASamples); + + if (this.ssaoRenderable.values.uCloseBias.ref.value !== props.occlusion.params.softAO.params.uASamples || + this.ssaoRenderable.values.uCloseDistance.ref.value !== props.occlusion.params.softAO.params.uARings) { + needsUpdateSsao = true; + } + } // console.log(light.direction); ValueCell.update(this.ssaoRenderable.values.uLightDirection, light.direction); diff --git a/src/mol-gl/shader/ssao.frag.ts b/src/mol-gl/shader/ssao.frag.ts index d849a80ef09ed5045a3440acc5f456ba704f984c..5a41821b694545ce67924828f6413a7775c905fe 100644 --- a/src/mol-gl/shader/ssao.frag.ts +++ b/src/mol-gl/shader/ssao.frag.ts @@ -33,13 +33,30 @@ uniform mat4 uInvProjection; uniform float uRadius; uniform float uBias; +// shadow uniform uniform float uSDistance; uniform float uSTolerance; uniform float uSBias; uniform int uShadow; + +//ssao-pro uniform uniform int uCloseAO; uniform float uCloseBias; uniform float uCloseDistance; +uniform float uCDistanceCutoff; +uniform float uCCutoffFalloff; +uniform float uCIntensity; +uniform float uCDistance; + +//ssao-old-blender uniform +uniform int uSoftAO; +uniform float uAorange; +uniform float uDepthTolerance; +uniform float uAoMultiplier; +uniform float uAoCap; +uniform float uAScale; +uniform int uARings; +uniform int uASamples; #define PI 3.14159265 #define SAMPLES_HIGH 1 @@ -73,6 +90,14 @@ bool outsideBounds(const in vec2 p) { return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w; } +float getViewZ(in float depth) { + #if dOrthographic == 1 + return orthographicDepthToViewZ(depth, uNear, uFar); + #else + return perspectiveDepthToViewZ(depth, uNear, uFar); + #endif +} + float getDepth(const in vec2 coords) { if (outsideBounds(coords)) { return 1.0; @@ -95,27 +120,35 @@ vec3 normalFromDepth(const in float depth, const in float depth1, const in float return normalize(normal); } -float compareDepths( in float depth1, in float depth2 ){ +float readDepth( in vec2 coord ) { + return (2.0 * uNear) / (uFar + uNear - getDepth(coord) * (uFar - uNear)); +} + +float compareDepths( in float d1, in float d2 ){ float near = uNear; float far = uFar; - float aorange = 160.0; //uniform - float depthTolerance = 0.0;//uniform - float aoMultiplier = 100.0;//uniform - float aoCap = 1.0;//uniform - float diff = sqrt(clamp(1.0-(depth1-depth2) / (aorange/(far-near)),0.0,1.0)); - float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff; + //float aorange = 160.0; //uniform + //float depthTolerance = 0.0;//uniform + //float aoMultiplier = 100.0;//uniform + //float aoCap = 1.0;//uniform + //go linear ? + float depth1 = d1;//getViewZ(d1); + float depth2 = d2;//getViewZ(d2); + //float diff = sqrt(clamp(1.0-(depth1-depth2) / (uAorange),0.0,1.0)); + float diff = sqrt(clamp(1.0-(depth1-depth2) / (uAorange/(far-near)),0.0,1.0)); + float ao = min(uAoCap,max(0.0,depth1-depth2-uDepthTolerance) * uAoMultiplier) * diff; return ao; } float computeAO(in vec2 scrCoord){ - float depth = getDepth(scrCoord); + float depth = readDepth(scrCoord); vec2 invTexSize = 1.0 / uTexSize; int do_noise = 0; - float scale = 1.0; //uniform + float scale = uAScale; //uniform float aspect = uTexSize.x/uTexSize.y; - int rings = min(6,int(uRadius)); //uniform - int samples = min(6,int(dNSamples)); //uniform + int rings = uARings;//min(6,int(uRadius)); //uniform + int samples = uASamples;//min(6,int(dNSamples)); //uniform //vec3 randomVec = normalize(vec3(getNoiseVec2(scrCoord), 0.0)); vec2 noise = getNoiseVec2(scrCoord);//getRandom(srcCoord);// float w; @@ -141,7 +174,7 @@ float computeAO(in vec2 scrCoord){ float step = PI*2.0 / float(ringsamples); pw = (cos(float(j)*step)*float(i)); ph = (sin(float(j)*step)*float(i))*aspect; - float v = getDepth( vec2(scrCoord.s+pw*w,scrCoord.t+ph*h)); + float v = readDepth( vec2(scrCoord.s+pw*w,scrCoord.t+ph*h) ); ao += compareDepths(depth, v); s += 1.0; } @@ -171,9 +204,9 @@ float computeOcclusion(in float aradius, in mat3 TBN, in vec3 selfViewPos ){ float calcAO(in vec2 tcoord, in vec2 uv, in vec3 p, in vec3 cnorm) { - float _Bias = 0.129; - float _Intensity = uCloseBias; - float _Distance = 0.001; + float _Bias = uCloseBias; + float _Intensity = uCIntensity; + float _Distance = uCDistance; vec2 t = tcoord + uv; float depth = getDepth(t); vec3 diff = screenSpaceToViewSpace(vec3(t, depth), uInvProjection) - p; @@ -188,14 +221,6 @@ float invlerp(float from, float to, float value) return (value - from) / (to - from); } -float getViewZ(const in float depth) { - #if dOrthographic == 1 - return orthographicDepthToViewZ(depth, uNear, uFar); - #else - return perspectiveDepthToViewZ(depth, uNear, uFar); - #endif -} - // Gold Noise function float PHI = 1.61803398874989484820459 * 00000.1; // Golden Ratio float PIT = 3.14159265358979323846264 * 00000.1; // PI @@ -209,8 +234,8 @@ float random_0t1(in vec2 coordinate, in float seed) float ssao(in vec2 uv, in vec3 normal) { float _SampleRadius = 5.0; - float _DistanceCutoff = 100.0; - float _CutoffFalloff = 25.0; + float _DistanceCutoff = uCDistanceCutoff;//100.0; + float _CutoffFalloff = uCCutoffFalloff;//25.0; vec2 CROSS[4] = vec2[4]( vec2(1.0, 0.0), vec2(-1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, -1.0) ); float depth = getDepth(uv); @@ -218,7 +243,7 @@ float ssao(in vec2 uv, in vec3 normal) vec3 position = screenSpaceToViewSpace(vec3(uv, depth), uInvProjection); float radius = uCloseDistance; // original was max(_SampleRadius / eyeDepth, 0.005); // clip(_DistanceCutoff - eyeDepth); // Skip out of range pixels - if (_DistanceCutoff - eyeDepth < 0.0) discard; + if (_DistanceCutoff - abs(eyeDepth) < 0.0) return 1.0; #if defined(SAMPLE_NOISE) float a = random_0t1(uv,depth); float b = random_0t1(uv,eyeDepth); @@ -360,17 +385,21 @@ void main(void) { float occlusion = computeOcclusion(uRadius, TBN, selfViewPos); occlusion = 1.0 - (uBias * occlusion / float(dNSamples)); - - /* + float ao1=0.0; // alternative ao algo - float ao = computeAO(selfCoords); - ao = clamp(ao,0.0,1.0); - if ( ao > 1.0 ) {ao = 1.0 ;} - if ( ao < 0.0 ) {ao = 0.0 ;} - if (selfDepth > 1.0 ) {ao = 1.0 ;} - if (selfDepth < 0.0 ) {ao = 0.0 ;} - ao = 1.0 - (uBias * ao); - */ + if (uSoftAO == 1) + { + ao1 = computeAO(selfCoords); + ao1 = clamp(ao1,0.0,1.0); + if ( ao1 > 1.0 ) {ao1 = 1.0 ;} + if ( ao1 < 0.0 ) {ao1 = 0.0 ;} + if (selfDepth > 1.0 ) {ao1 = 1.0 ;} + if (selfDepth < 0.0 ) {ao1 = 0.0 ;} + ao1 = 1.0 - (ao1); + } + + bool isClose = true; + if (abs(selfViewPos.z) > 1200.0) isClose = false; float ao = 1.0; if (uCloseAO == 1){ @@ -391,6 +420,9 @@ void main(void) { else{ o = min(ao,occlusion); } + if (uSoftAO==1){ + o = min(ao1,o); + } vec2 packedOcclusion = packUnitIntervalToRG(o); gl_FragColor = vec4(packedOcclusion, selfPackedDepth); } diff --git a/src/mol-plugin-ui/structure/quick-styles.tsx b/src/mol-plugin-ui/structure/quick-styles.tsx index 8b5a38ebe1d276f6cc243c0058e6cff9af91c8dd..262f10f6b515c70126293e116edd75fbc16b8c0d 100644 --- a/src/mol-plugin-ui/structure/quick-styles.tsx +++ b/src/mol-plugin-ui/structure/quick-styles.tsx @@ -60,7 +60,7 @@ export class QuickStyles extends PurePluginUIComponent { }, occlusion: { name: 'on', - params: { bias: 0.8, blurKernelSize: 15, radius: 5, samples: 32, resolutionScale: 1, shadow: { name: 'off', params: {} }, closeAO: { name: 'off', params: {} } } + params: { bias: 0.8, blurKernelSize: 15, radius: 5, samples: 32, resolutionScale: 1, shadow: { name: 'off', params: {} }, softAO: { name: 'off', params: {} }, closeAO: { name: 'off', params: {} } } } } });