diff --git a/package.json b/package.json index 7283779d1b43c0d1cc42699743ce8a5f66206e8f..98bdfc14039c5dbfa4d963e103466396ed2c36bc 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "Alexander Rose <alexander.rose@weirdbyte.de>", "David Sehnal <david.sehnal@gmail.com>", "Sebastian Bittrich <sebastian.bittrich@rcsb.org>", + "Ăron Samuel Kovács <aron.kovacs@mail.muni.cz>", "Ludovic Autin <autin@scripps.edu>", "Michal MalĂ˝ <michal.maly@ibt.cas.cz>", "Jiřà ČernĂ˝ <jiri.cerny@ibt.cas.cz>" diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index b9860ebc942af1c99668a39b3c80ca1c4519e620..504b51da8e9ca16e04b8d966effccd001232978d 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -310,7 +310,7 @@ namespace Canvas3D { if (MultiSamplePass.isEnabled(p.multiSample)) { multiSampleHelper.render(renderer, cam, scene, helper, true, p.transparentBackground, p); } else { - passes.draw.render(renderer, cam, scene, helper, true, p.renderer.backgroundColor, p.transparentBackground, p.postprocessing); + passes.draw.render(renderer, cam, scene, helper, true, p.transparentBackground, p.postprocessing); } pickHelper.dirty = true; didRender = true; diff --git a/src/mol-canvas3d/passes/draw.ts b/src/mol-canvas3d/passes/draw.ts index 4224ea482f425f2631bc1bd4fd8942c74522fd51..452ee69a57967ecf92fc4216c2a59edfc1788a2d 100644 --- a/src/mol-canvas3d/passes/draw.ts +++ b/src/mol-canvas3d/passes/draw.ts @@ -26,7 +26,6 @@ import copyFbo_frag from '../../mol-gl/shader/copy-fbo.frag'; import { StereoCamera } from '../camera/stereo'; import { WboitPass } from './wboit'; import { AntialiasingPass, PostprocessingPass, PostprocessingProps } from './postprocessing'; -import { Color } from '../../mol-util/color'; const DepthMergeSchema = { ...QuadSchema, @@ -59,7 +58,7 @@ const CopyFboSchema = { tDepth: TextureSpec('texture', 'depth', 'ushort', 'nearest'), uTexSize: UniformSpec('v2'), }; -const CopyFboShaderCode = ShaderCode('copy-fbo', quad_vert, copyFbo_frag); +const CopyFboShaderCode = ShaderCode('copy-fbo', quad_vert, copyFbo_frag, { fragDepth: 'required' }); type CopyFboRenderable = ComputeRenderable<Values<typeof CopyFboSchema>> function getCopyFboRenderable(ctx: WebGLContext, colorTexture: Texture, depthTexture: Texture): CopyFboRenderable { @@ -96,7 +95,7 @@ export class DrawPass { private wboit: WboitPass | undefined readonly postprocessing: PostprocessingPass - private readonly fxaa: AntialiasingPass + private readonly antialiasing: AntialiasingPass get wboitEnabled() { return !!this.wboit?.supported; @@ -126,7 +125,7 @@ export class DrawPass { this.wboit = enableWboit ? new WboitPass(webgl, width, height) : undefined; this.postprocessing = new PostprocessingPass(webgl, this); - this.fxaa = new AntialiasingPass(webgl, this); + this.antialiasing = new AntialiasingPass(webgl, this); this.copyFboTarget = getCopyFboRenderable(webgl, this.colorTarget.texture, this.depthTarget.texture); this.copyFboPostprocessing = getCopyFboRenderable(webgl, this.postprocessing.target.texture, this.depthTarget.texture); @@ -162,7 +161,7 @@ export class DrawPass { } this.postprocessing.setSize(width, height); - this.fxaa.setSize(width, height); + this.antialiasing.setSize(width, height); } } @@ -180,7 +179,7 @@ export class DrawPass { this.depthMerge.render(); } - private _renderWboit(renderer: Renderer, camera: ICamera, scene: Scene, backgroundColor: Color, postprocessingProps: PostprocessingProps) { + private _renderWboit(renderer: Renderer, camera: ICamera, scene: Scene, transparentBackground: boolean, postprocessingProps: PostprocessingProps) { if (!this.wboit?.supported) throw new Error('expected wboit to be supported'); this.colorTarget.bind(); @@ -202,7 +201,7 @@ export class DrawPass { this._depthMerge(); if (PostprocessingPass.isEnabled(postprocessingProps)) { - this.postprocessing.render(camera, false, backgroundColor, postprocessingProps); + this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps); } // render transparent primitives and volumes @@ -221,7 +220,7 @@ export class DrawPass { this.wboit.render(); } - private _renderBlended(renderer: Renderer, camera: ICamera, scene: Scene, backgroundColor: Color, toDrawingBuffer: boolean, postprocessingProps: PostprocessingProps) { + private _renderBlended(renderer: Renderer, camera: ICamera, scene: Scene, toDrawingBuffer: boolean, transparentBackground: boolean, postprocessingProps: PostprocessingProps) { if (toDrawingBuffer) { this.drawTarget.bind(); } else { @@ -264,7 +263,7 @@ export class DrawPass { this.colorTarget.bind(); if (PostprocessingPass.isEnabled(postprocessingProps)) { - this.postprocessing.render(camera, false, backgroundColor, postprocessingProps); + this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps); } renderer.renderBlendedVolumeTransparent(scene.volumes, camera, this.depthTexturePrimitives); @@ -284,7 +283,7 @@ export class DrawPass { renderer.renderBlendedTransparent(scene.primitives, camera, null); } - private _render(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, backgroundColor: Color, postprocessingProps: PostprocessingProps) { + private _render(renderer: Renderer, camera: ICamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, postprocessingProps: PostprocessingProps) { const volumeRendering = scene.volumes.renderables.length > 0; const postprocessingEnabled = PostprocessingPass.isEnabled(postprocessingProps); const antialiasingEnabled = AntialiasingPass.isEnabled(postprocessingProps); @@ -294,9 +293,9 @@ export class DrawPass { renderer.update(camera); if (this.wboitEnabled) { - this._renderWboit(renderer, camera, scene, backgroundColor, postprocessingProps); + this._renderWboit(renderer, camera, scene, transparentBackground, postprocessingProps); } else { - this._renderBlended(renderer, camera, scene, backgroundColor, !volumeRendering && !postprocessingEnabled && !antialiasingEnabled && toDrawingBuffer, postprocessingProps); + this._renderBlended(renderer, camera, scene, !volumeRendering && !postprocessingEnabled && !antialiasingEnabled && toDrawingBuffer, transparentBackground, postprocessingProps); } if (PostprocessingPass.isEnabled(postprocessingProps)) { @@ -321,7 +320,7 @@ export class DrawPass { } if (antialiasingEnabled) { - this.fxaa.render(camera, toDrawingBuffer, postprocessingProps); + this.antialiasing.render(camera, toDrawingBuffer, postprocessingProps); } else if (toDrawingBuffer) { this.drawTarget.bind(); @@ -336,21 +335,21 @@ export class DrawPass { this.webgl.gl.flush(); } - render(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, backgroundColor: Color, transparentBackground: boolean, postprocessingProps: PostprocessingProps) { + render(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, postprocessingProps: PostprocessingProps) { renderer.setTransparentBackground(transparentBackground); renderer.setDrawingBufferSize(this.colorTarget.getWidth(), this.colorTarget.getHeight()); if (StereoCamera.is(camera)) { - this._render(renderer, camera.left, scene, helper, toDrawingBuffer, backgroundColor, postprocessingProps); - this._render(renderer, camera.right, scene, helper, toDrawingBuffer, backgroundColor, postprocessingProps); + this._render(renderer, camera.left, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps); + this._render(renderer, camera.right, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps); } else { - this._render(renderer, camera, scene, helper, toDrawingBuffer, backgroundColor, postprocessingProps); + this._render(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, postprocessingProps); } } getColorTarget(postprocessingProps: PostprocessingProps): RenderTarget { if (AntialiasingPass.isEnabled(postprocessingProps)) { - return this.fxaa.target; + return this.antialiasing.target; } else if (PostprocessingPass.isEnabled(postprocessingProps)) { return this.postprocessing.target; } diff --git a/src/mol-canvas3d/passes/fxaa.ts b/src/mol-canvas3d/passes/fxaa.ts index 3f1d8c4ac28d355f96fb8e88c30d4a462d88ee5c..efdd545df960aa625b39e0d2708f023418354211 100644 --- a/src/mol-canvas3d/passes/fxaa.ts +++ b/src/mol-canvas3d/passes/fxaa.ts @@ -16,6 +16,8 @@ import { ValueCell } from '../../mol-util'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import quad_vert from '../../mol-gl/shader/quad.vert'; import fxaa_frag from '../../mol-gl/shader/fxaa.frag'; +import { Viewport } from '../camera/util'; +import { RenderTarget } from '../../mol-gl/webgl/render-target'; export const FxaaParams = { edgeThresholdMin: PD.Numeric(0.0312, { min: 0.0312, max: 0.0833, step: 0.0001 }, { description: 'Trims the algorithm from processing darks.' }), @@ -28,10 +30,26 @@ export type FxaaProps = PD.Values<typeof FxaaParams> export class FxaaPass { private readonly renderable: FxaaRenderable - constructor(webgl: WebGLContext, input: Texture) { + constructor(private webgl: WebGLContext, input: Texture) { this.renderable = getFxaaRenderable(webgl, input); } + private updateState(viewport: Viewport) { + const { gl, state } = this.webgl; + + state.enable(gl.SCISSOR_TEST); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.depthMask(false); + + const { x, y, width, height } = viewport; + gl.viewport(x, y, width, height); + gl.scissor(x, y, width, height); + + state.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + } + setSize(width: number, height: number) { ValueCell.update(this.renderable.values.uTexSizeInv, Vec2.set(this.renderable.values.uTexSizeInv.ref.value, 1 / width, 1 / height)); } @@ -64,7 +82,13 @@ export class FxaaPass { } } - render() { + render(viewport: Viewport, target: RenderTarget | undefined) { + if (target) { + target.bind(); + } else { + this.webgl.unbindFramebuffer(); + } + this.updateState(viewport); this.renderable.render(); } } diff --git a/src/mol-canvas3d/passes/image.ts b/src/mol-canvas3d/passes/image.ts index 89e0aa1ef0f70967d88e66937a9fd4de28d79783..1fbe7c946acdf8c36f7475e75b33d8ac78acf9be 100644 --- a/src/mol-canvas3d/passes/image.ts +++ b/src/mol-canvas3d/passes/image.ts @@ -17,7 +17,6 @@ import { Viewport } from '../camera/util'; import { PixelData } from '../../mol-util/image'; import { Helper } from '../helper/helper'; import { CameraHelper, CameraHelperParams } from '../helper/camera-helper'; -import { Color } from '../../mol-util/color'; export const ImageParams = { transparentBackground: PD.Boolean(false), @@ -86,7 +85,7 @@ export class ImagePass { this.multiSampleHelper.render(this.renderer, this._camera, this.scene, this.helper, false, this.props.transparentBackground, this.props); this._colorTarget = this.multiSamplePass.colorTarget; } else { - this.drawPass.render(this.renderer, this._camera, this.scene, this.helper, false, Color(0xffffff), this.props.transparentBackground, this.props.postprocessing); + this.drawPass.render(this.renderer, this._camera, this.scene, this.helper, false, this.props.transparentBackground, this.props.postprocessing); this._colorTarget = this.drawPass.getColorTarget(this.props.postprocessing); } } diff --git a/src/mol-canvas3d/passes/multi-sample.ts b/src/mol-canvas3d/passes/multi-sample.ts index c3b96eb642806191e58a253ecc4fde3028994d24..c5e9d4f7fc0dc1d220c1d15d2e47a7ddc22853a9 100644 --- a/src/mol-canvas3d/passes/multi-sample.ts +++ b/src/mol-canvas3d/passes/multi-sample.ts @@ -25,7 +25,6 @@ import { StereoCamera } from '../camera/stereo'; import quad_vert from '../../mol-gl/shader/quad.vert'; import compose_frag from '../../mol-gl/shader/compose.frag'; -import { Color } from '../../mol-util/color'; const ComposeSchema = { ...QuadSchema, @@ -143,7 +142,7 @@ export class MultiSamplePass { ValueCell.update(compose.values.uWeight, sampleWeight); // render scene - drawPass.render(renderer, camera, scene, helper, false, Color(0xffffff), transparentBackground, props.postprocessing); + drawPass.render(renderer, camera, scene, helper, false, transparentBackground, props.postprocessing); // compose rendered scene with compose target composeTarget.bind(); @@ -193,7 +192,7 @@ export class MultiSamplePass { const sampleWeight = 1.0 / offsetList.length; if (sampleIndex === -1) { - drawPass.render(renderer, camera, scene, helper, false, Color(0xffffff), transparentBackground, props.postprocessing); + drawPass.render(renderer, camera, scene, helper, false, transparentBackground, props.postprocessing); ValueCell.update(compose.values.uWeight, 1.0); ValueCell.update(compose.values.tColor, drawPass.getColorTarget(props.postprocessing).texture); compose.update(); @@ -221,7 +220,7 @@ export class MultiSamplePass { camera.update(); // render scene - drawPass.render(renderer, camera, scene, helper, false, Color(0xffffff), transparentBackground, props.postprocessing); + drawPass.render(renderer, camera, scene, helper, false, transparentBackground, props.postprocessing); // compose rendered scene with compose target composeTarget.bind(); diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index 5747c8d294d5f8ab7095f5ecaa7204ad74d008e4..7b53cf929fb38d00c55093e0dfd86ae09e395c42 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -184,26 +184,24 @@ const PostprocessingSchema = { uTexSize: UniformSpec('v2'), dOrthographic: DefineSpec('number'), - uInvProjection: UniformSpec('m4'), uNear: UniformSpec('f'), uFar: UniformSpec('f'), uFogNear: UniformSpec('f'), uFogFar: UniformSpec('f'), uFogColor: UniformSpec('v3'), + uTransparentBackground: UniformSpec('b'), uMaxPossibleViewZDiff: UniformSpec('f'), dOcclusionEnable: DefineSpec('boolean'), dOutlineEnable: DefineSpec('boolean'), - uOutlineScale: UniformSpec('f'), + dOutlineScale: DefineSpec('number'), uOutlineThreshold: UniformSpec('f'), - - dPackedDepth: DefineSpec('boolean'), }; type PostprocessingRenderable = ComputeRenderable<Values<typeof PostprocessingSchema>> -function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTexture: Texture, packedDepth: boolean, outlinesTexture: Texture, ssaoDepthTexture: Texture): PostprocessingRenderable { +function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTexture: Texture, outlinesTexture: Texture, ssaoDepthTexture: Texture): PostprocessingRenderable { const values: Values<typeof PostprocessingSchema> = { ...QuadValues, tSsaoDepth: ValueCell.create(ssaoDepthTexture), @@ -213,22 +211,20 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d uTexSize: ValueCell.create(Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())), dOrthographic: ValueCell.create(0), - uInvProjection: ValueCell.create(Mat4.identity()), uNear: ValueCell.create(1), uFar: ValueCell.create(10000), uFogNear: ValueCell.create(10000), uFogFar: ValueCell.create(10000), uFogColor: ValueCell.create(Vec3.create(1, 1, 1)), + uTransparentBackground: ValueCell.create(false), uMaxPossibleViewZDiff: ValueCell.create(0.5), dOcclusionEnable: ValueCell.create(false), dOutlineEnable: ValueCell.create(false), - uOutlineScale: ValueCell.create(ctx.pixelRatio), - uOutlineThreshold: ValueCell.create(0.8), - - dPackedDepth: ValueCell.create(packedDepth), + dOutlineScale: ValueCell.create(1), + uOutlineThreshold: ValueCell.create(0.33), }; const schema = { ...PostprocessingSchema }; @@ -242,9 +238,9 @@ export const PostprocessingParams = { occlusion: PD.MappedStatic('off', { on: PD.Group({ samples: PD.Numeric(64, {min: 1, max: 256, step: 1}), - radius: PD.Numeric(8.0, { min: 1, max: 64, step: 1 }), - bias: PD.Numeric(1.0, { min: 0, max: 1, step: 0.001 }), - blurKernelSize: PD.Numeric(13, { min: 1, max: 25, step: 2 }), + radius: PD.Numeric(24.0, { min: 1, max: 64, step: 1 }), + bias: PD.Numeric(1.2, { min: 0, max: 2, step: 0.1 }), + blurKernelSize: PD.Numeric(20, { min: 1, max: 25, step: 2 }), }), off: PD.Group({}) }, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }), @@ -291,7 +287,7 @@ export class PostprocessingPass { private readonly renderable: PostprocessingRenderable constructor(private webgl: WebGLContext, drawPass: DrawPass) { - const { colorTarget, depthTexture, packedDepth } = drawPass; + const { colorTarget, depthTexture } = drawPass; const width = colorTarget.getWidth(); const height = colorTarget.getHeight(); @@ -330,7 +326,7 @@ export class PostprocessingPass { this.ssaoRenderable = getSsaoRenderable(webgl, depthTexture); this.ssaoBlurFirstPassRenderable = getSsaoBlurRenderable(webgl, this.ssaoDepthTexture, 'horizontal'); this.ssaoBlurSecondPassRenderable = getSsaoBlurRenderable(webgl, this.ssaoDepthBlurProxyTexture, 'vertical'); - this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTexture, packedDepth, this.outlinesTarget.texture, this.ssaoDepthTexture); + this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTexture, this.outlinesTarget.texture, this.ssaoDepthTexture); } setSize(width: number, height: number) { @@ -349,14 +345,14 @@ export class PostprocessingPass { } } - private updateState(camera: ICamera, backgroundColor: Color, props: PostprocessingProps) { + private updateState(camera: ICamera, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps) { let needsUpdateMain = false; let needsUpdateSsao = false; let needsUpdateSsaoBlur = false; - let orthographic = camera.state.mode === 'orthographic' ? 1 : 0; - let outlinesEnabled = props.outline.name === 'on'; - let occlusionEnabled = props.occlusion.name === 'on'; + const orthographic = camera.state.mode === 'orthographic' ? 1 : 0; + const outlinesEnabled = props.outline.name === 'on'; + const occlusionEnabled = props.occlusion.name === 'on'; let invProjection = Mat4.identity(); Mat4.invert(invProjection, camera.projection); @@ -400,26 +396,26 @@ export class PostprocessingPass { } if (props.outline.name === 'on') { - let factor = Math.pow(1000, props.outline.params.threshold) / 1000; - let maxPossibleViewZDiff = factor * (camera.far - camera.near); + const factor = Math.pow(1000, props.outline.params.threshold) / 1000; + const maxPossibleViewZDiff = factor * (camera.far - camera.near); + const outlineScale = props.outline.params.scale - 1; ValueCell.updateIfChanged(this.outlinesRenderable.values.uNear, camera.near); ValueCell.updateIfChanged(this.outlinesRenderable.values.uFar, camera.far); ValueCell.updateIfChanged(this.outlinesRenderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff); - ValueCell.updateIfChanged(this.renderable.values.uInvProjection, invProjection); ValueCell.updateIfChanged(this.renderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff); - let fogColor = Vec3(); - Color.toVec3Normalized(fogColor, backgroundColor); - ValueCell.updateIfChanged(this.renderable.values.uFogColor, fogColor); - ValueCell.updateIfChanged(this.renderable.values.uOutlineScale, props.outline.params.scale - 1); ValueCell.updateIfChanged(this.renderable.values.uOutlineThreshold, props.outline.params.threshold); + if (this.renderable.values.dOutlineScale.ref.value !== outlineScale) { needsUpdateMain = true; } + ValueCell.updateIfChanged(this.renderable.values.dOutlineScale, outlineScale); } ValueCell.updateIfChanged(this.renderable.values.uFar, camera.far); ValueCell.updateIfChanged(this.renderable.values.uNear, camera.near); ValueCell.updateIfChanged(this.renderable.values.uFogFar, camera.fogFar); ValueCell.updateIfChanged(this.renderable.values.uFogNear, camera.fogNear); + ValueCell.update(this.renderable.values.uFogColor, Color.toVec3Normalized(this.renderable.values.uFogColor.ref.value, backgroundColor)); + ValueCell.updateIfChanged(this.renderable.values.uTransparentBackground, transparentBackground); if (this.renderable.values.dOrthographic.ref.value !== orthographic) { needsUpdateMain = true; } ValueCell.updateIfChanged(this.renderable.values.dOrthographic, orthographic); if (this.renderable.values.dOutlineEnable.ref.value !== outlinesEnabled) { needsUpdateMain = true; } @@ -452,8 +448,8 @@ export class PostprocessingPass { gl.scissor(x, y, width, height); } - render(camera: ICamera, toDrawingBuffer: boolean, backgroundColor: Color, props: PostprocessingProps) { - this.updateState(camera, backgroundColor, props); + render(camera: ICamera, toDrawingBuffer: boolean, transparentBackground: boolean, backgroundColor: Color, props: PostprocessingProps) { + this.updateState(camera, transparentBackground, backgroundColor, props); if (props.outline.name === 'on') { this.outlinesTarget.bind(); @@ -494,7 +490,7 @@ export class AntialiasingPass { private readonly fxaa: FxaaPass private readonly smaa: SmaaPass - constructor(private webgl: WebGLContext, private drawPass: DrawPass) { + constructor(webgl: WebGLContext, private drawPass: DrawPass) { const { colorTarget } = drawPass; const width = colorTarget.getWidth(); const height = colorTarget.getHeight(); @@ -505,7 +501,9 @@ export class AntialiasingPass { } setSize(width: number, height: number) { - const [w, h] = [this.target.texture.getWidth(), this.target.texture.getHeight()]; + const w = this.target.texture.getWidth(); + const h = this.target.texture.getHeight(); + if (width !== w || height !== h) { this.target.setSize(width, height); this.fxaa.setSize(width, height); @@ -513,22 +511,6 @@ export class AntialiasingPass { } } - private updateState(camera: ICamera) { - const { gl, state } = this.webgl; - - state.enable(gl.SCISSOR_TEST); - state.disable(gl.BLEND); - state.disable(gl.DEPTH_TEST); - state.depthMask(false); - - const { x, y, width, height } = camera.viewport; - gl.viewport(x, y, width, height); - gl.scissor(x, y, width, height); - - state.clearColor(0, 0, 0, 1); - gl.clear(gl.COLOR_BUFFER_BIT); - } - private _renderFxaa(camera: ICamera, toDrawingBuffer: boolean, props: PostprocessingProps) { if (props.antialiasing.name !== 'fxaa') return; @@ -536,15 +518,7 @@ export class AntialiasingPass { ? this.drawPass.postprocessing.target.texture : this.drawPass.colorTarget.texture; this.fxaa.update(input, props.antialiasing.params); - - if (toDrawingBuffer) { - this.webgl.unbindFramebuffer(); - } else { - this.target.bind(); - } - - this.updateState(camera); - this.fxaa.render(); + this.fxaa.render(camera.viewport, toDrawingBuffer ? undefined : this.target); } private _renderSmaa(camera: ICamera, toDrawingBuffer: boolean, props: PostprocessingProps) { @@ -554,7 +528,6 @@ export class AntialiasingPass { ? this.drawPass.postprocessing.target.texture : this.drawPass.colorTarget.texture; this.smaa.update(input, props.antialiasing.params); - this.smaa.render(camera.viewport, toDrawingBuffer ? undefined : this.target); } diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 88da0af16e68f83d3987883cb989b857c6631332..b77befbe4c4f4d3f27c226097ba89a7bd1f01607 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -632,9 +632,7 @@ namespace Renderer { } }, - get props() { - return p; - }, + props: p, get stats(): RendererStats { return { programCount: ctx.stats.resourceCounts.program, diff --git a/src/mol-gl/shader/chunks/apply-fog.glsl.ts b/src/mol-gl/shader/chunks/apply-fog.glsl.ts index f0df92dbb753c75b1d1507bae7c632106eef6729..6c0e22d2e3dc48fe4befce65c4117e2ff2226cd9 100644 --- a/src/mol-gl/shader/chunks/apply-fog.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-fog.glsl.ts @@ -1,5 +1,8 @@ export default ` -float fogDepth = length(vViewPosition); +float viewZ = uIsOrtho == 1.0 + ? orthographicDepthToViewZ(fragmentDepth, uNear, uFar) + : perspectiveDepthToViewZ(fragmentDepth, uNear, uFar); +float fogDepth = abs(viewZ); float fogFactor = smoothstep(uFogNear, uFogFar, fogDepth); float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a; float preFogAlpha = gl_FragColor.a; diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts index 6c784e73b062809b0f6d047331e8b5f3eca14c9a..562629ec1a59d6f0cdc21c1fbb644e3fd2f38d89 100644 --- a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts @@ -31,6 +31,10 @@ varying vec3 vViewPosition; uniform vec2 uViewOffset; +uniform float uNear; +uniform float uFar; +uniform float uIsOrtho; + uniform float uFogNear; uniform float uFogFar; uniform vec3 uFogColor; diff --git a/src/mol-gl/shader/chunks/common.glsl.ts b/src/mol-gl/shader/chunks/common.glsl.ts index 077baa036bd8bf81b3b565c9a187a5b4f09e7580..aa0a13792bf886ee2cbb870363122b6b774423a6 100644 --- a/src/mol-gl/shader/chunks/common.glsl.ts +++ b/src/mol-gl/shader/chunks/common.glsl.ts @@ -28,7 +28,7 @@ export default ` float intDiv(const in float a, const in float b) { return float(int(a) / int(b)); } float intMod(const in float a, const in float b) { return a - b * float(int(a) / int(b)); } -float pow2(const in float x) { return x*x; } +float pow2(const in float x) { return x * x; } const float maxFloat = 10000.0; // NOTE constant also set in TypeScript const float floatLogFactor = 9.210440366976517; // log(maxFloat + 1.0); @@ -90,10 +90,18 @@ vec4 linearTosRGB(const in vec4 c) { return vec4(mix(pow(c.rgb, vec3(0.41666)) * 1.055 - vec3(0.055), c.rgb * 12.92, vec3(lessThanEqual(c.rgb, vec3(0.0031308)))), c.a); } -float linearizeDepth(in float depth, in float near, in float far) { +float linearizeDepth(const in float depth, const in float near, const in float far) { return (2.0 * near) / (far + near - depth * (far - near)); } +float perspectiveDepthToViewZ(const in float invClipZ, const in float near, const in float far) { + return (near * far) / ((far - near) * invClipZ - far); +} + +float orthographicDepthToViewZ(const in float linearClipZ, const in float near, const in float far) { + return linearClipZ * (near - far) - near; +} + #if __VERSION__ != 300 // transpose diff --git a/src/mol-gl/shader/cylinders.frag.ts b/src/mol-gl/shader/cylinders.frag.ts index bfa204d53c292d6c3ab030b9dafdd37d1ab04af4..a99548808c6cfda6c082a6c578c9525030e94ab6 100644 --- a/src/mol-gl/shader/cylinders.frag.ts +++ b/src/mol-gl/shader/cylinders.frag.ts @@ -17,7 +17,6 @@ varying float vSize; varying float vCap; uniform vec3 uCameraDir; -uniform float uIsOrtho; uniform vec3 uCameraPosition; #include common @@ -132,9 +131,9 @@ void main() { #include apply_interior_color #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragDepthEXT; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/direct-volume.frag.ts b/src/mol-gl/shader/direct-volume.frag.ts index 7bbd2e7c1d8916671524132e01abe78ac875aaf0..b4a5195f2a512548ed59f4a966648472c642813f 100644 --- a/src/mol-gl/shader/direct-volume.frag.ts +++ b/src/mol-gl/shader/direct-volume.frag.ts @@ -30,8 +30,6 @@ uniform vec3 uCameraDir; uniform sampler2D tDepth; uniform vec2 uDrawingBufferSize; -uniform float uNear; -uniform float uFar; varying vec3 vOrigPos; varying float vInstance; @@ -70,6 +68,8 @@ uniform bool uInteriorColorFlag; uniform vec3 uInteriorColor; bool interior; +uniform float uNear; +uniform float uFar; uniform float uIsOrtho; uniform vec3 uCellDim; @@ -166,6 +166,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { vec4 src = vec4(0.0); vec4 dst = vec4(0.0); bool hit = false; + float fragmentDepth; vec3 posMin = vec3(0.0); vec3 posMax = vec3(1.0) - vec3(1.0) / uGridDim; @@ -325,6 +326,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { #include apply_marker_color preFogAlphaBlended = (1.0 - preFogAlphaBlended) * gl_FragColor.a + preFogAlphaBlended; + fragmentDepth = depth; #include apply_fog src = gl_FragColor; @@ -393,6 +395,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { #include apply_marker_color preFogAlphaBlended = (1.0 - preFogAlphaBlended) * gl_FragColor.a + preFogAlphaBlended; + fragmentDepth = calcDepth(mvPosition.xyz); #include apply_fog src = gl_FragColor; @@ -424,7 +427,7 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { // TODO: support float texture for higher precision values??? // TODO: support clipping exclusion texture support -void main () { +void main() { if (gl_FrontFacing) discard; diff --git a/src/mol-gl/shader/image.frag.ts b/src/mol-gl/shader/image.frag.ts index 995f4797dc6ac124d7e82696b7e070a7d375d227..a1016277ed046ce2496be737f46c9efac343fdad 100644 --- a/src/mol-gl/shader/image.frag.ts +++ b/src/mol-gl/shader/image.frag.ts @@ -122,10 +122,10 @@ void main() { float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb); float vMarker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragCoord.z; bool interior = false; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/lines.frag.ts b/src/mol-gl/shader/lines.frag.ts index e85fb79e6cc3e8c3c71740e28059ebc115311446..07662650f258c849ed90e08a46e20f990cd67840 100644 --- a/src/mol-gl/shader/lines.frag.ts +++ b/src/mol-gl/shader/lines.frag.ts @@ -27,10 +27,10 @@ void main(){ gl_FragColor = material; #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragCoord.z; bool interior = false; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/mesh.frag.ts b/src/mol-gl/shader/mesh.frag.ts index 1884c5be13766e905138eba3779aaf1650c81dd8..722fac201a5538fd139d648cc600f9012943e6a4 100644 --- a/src/mol-gl/shader/mesh.frag.ts +++ b/src/mol-gl/shader/mesh.frag.ts @@ -59,9 +59,9 @@ void main() { #include apply_interior_color #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragCoord.z; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/outlines.frag.ts b/src/mol-gl/shader/outlines.frag.ts index 19f91fc381dedd8c9da325303f81f43b1bc2d048..283c59959bb01bef3777574c1a121f1983a6e17d 100644 --- a/src/mol-gl/shader/outlines.frag.ts +++ b/src/mol-gl/shader/outlines.frag.ts @@ -19,14 +19,6 @@ uniform float uMaxPossibleViewZDiff; #include common -float perspectiveDepthToViewZ(const in float invClipZ, const in float near, const in float far) { - return (near * far) / ((far - near) * invClipZ - far); -} - -float orthographicDepthToViewZ(const in float linearClipZ, const in float near, const in float far) { - return linearClipZ * (near - far) - near; -} - float getViewZ(const in float depth) { #if dOrthographic == 1 return orthographicDepthToViewZ(depth, uNear, uFar); @@ -45,7 +37,7 @@ bool isBackground(const in float depth) { void main(void) { float backgroundViewZ = uFar + 3.0 * uMaxPossibleViewZDiff; - + vec2 coords = gl_FragCoord.xy / uTexSize; vec2 invTexSize = 1.0 / uTexSize; diff --git a/src/mol-gl/shader/points.frag.ts b/src/mol-gl/shader/points.frag.ts index 9aefed044b946219f472c51510a7c113b9e97d89..186485d669c326866861e66db8948da52bf783cd 100644 --- a/src/mol-gl/shader/points.frag.ts +++ b/src/mol-gl/shader/points.frag.ts @@ -41,10 +41,10 @@ void main(){ #endif #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragCoord.z; bool interior = false; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/postprocessing.frag.ts b/src/mol-gl/shader/postprocessing.frag.ts index ecc9e5153c782e992ac7b5f3406ec09f69b7db50..3869820c29902a5947ca1bb4f864c574b7849be4 100644 --- a/src/mol-gl/shader/postprocessing.frag.ts +++ b/src/mol-gl/shader/postprocessing.frag.ts @@ -16,12 +16,12 @@ uniform sampler2D tDepth; uniform sampler2D tOutlines; uniform vec2 uTexSize; -uniform mat4 uInvProjection; uniform float uNear; uniform float uFar; uniform float uFogNear; uniform float uFogFar; uniform vec3 uFogColor; +uniform bool uTransparentBackground; uniform float uOcclusionBias; uniform float uOcclusionRadius; @@ -31,18 +31,10 @@ uniform float uOutlineThreshold; uniform float uMaxPossibleViewZDiff; -const vec4 occlusionColor = vec4(0.0, 0.0, 0.0, 1.0); +const vec3 occlusionColor = vec3(0.0); #include common -float perspectiveDepthToViewZ(const in float invClipZ, const in float near, const in float far) { - return (near * far) / ((far - near) * invClipZ - far); -} - -float orthographicDepthToViewZ(const in float linearClipZ, const in float near, const in float far) { - return linearClipZ * (near - far) - near; -} - float getViewZ(const in float depth) { #if dOrthographic == 1 return orthographicDepthToViewZ(depth, uNear, uFar); @@ -64,25 +56,23 @@ float getOutline(const in vec2 coords, out float closestTexel) { vec2 invTexSize = 1.0 / uTexSize; float selfDepth = getDepth(coords); - float selfViewZ = isBackground(selfDepth) ? backgroundViewZ : getViewZ(getDepth(coords)); + float selfViewZ = isBackground(selfDepth) ? backgroundViewZ : getViewZ(selfDepth); float outline = 1.0; - closestTexel = backgroundViewZ; - for (float y = -uOutlineScale; y <= uOutlineScale; y++) { - for (float x = -uOutlineScale; x <= uOutlineScale; x++) { - if (x * x + y * y > uOutlineScale * uOutlineScale) { + closestTexel = 1.0; + for (int y = -dOutlineScale; y <= dOutlineScale; y++) { + for (int x = -dOutlineScale; x <= dOutlineScale; x++) { + if (x * x + y * y > dOutlineScale * dOutlineScale) { continue; } - vec2 sampleCoords = coords + vec2(x, y) * invTexSize; + vec2 sampleCoords = coords + vec2(float(x), float(y)) * invTexSize; vec4 sampleOutlineCombined = texture2D(tOutlines, sampleCoords); float sampleOutline = sampleOutlineCombined.r; float sampleOutlineDepth = unpackRGToUnitInterval(sampleOutlineCombined.gb); - float sampleOutlineViewDirLength = length(screenSpaceToViewSpace(vec3(sampleCoords, sampleOutlineDepth), uInvProjection)); - - if (sampleOutline == 0.0 && sampleOutlineViewDirLength < closestTexel && abs(selfViewZ - sampleOutlineDepth) > uMaxPossibleViewZDiff) { + if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel && abs(selfViewZ - sampleOutlineDepth) > uMaxPossibleViewZDiff) { outline = 0.0; closestTexel = sampleOutlineDepth; } @@ -92,7 +82,7 @@ float getOutline(const in vec2 coords, out float closestTexel) { } float getSsao(vec2 coords) { - float rawSsao = unpackRGToUnitInterval(texture(tSsaoDepth, coords).xy); + float rawSsao = unpackRGToUnitInterval(texture2D(tSsaoDepth, coords).xy); if (rawSsao > 0.999) { return 1.0; } else if (rawSsao > 0.001) { @@ -103,7 +93,10 @@ float getSsao(vec2 coords) { void main(void) { vec2 coords = gl_FragCoord.xy / uTexSize; - vec4 color = texture(tColor, coords); + vec4 color = texture2D(tColor, coords); + + float viewDist; + float fogFactor; #ifdef dOutlineEnable float closestTexel; @@ -111,12 +104,13 @@ void main(void) { if (outline == 0.0) { color.rgb *= outline; - float viewDist = abs(getViewZ(closestTexel)); - float fogFactor = smoothstep(uFogNear, uFogFar, viewDist); - if (color.a != 1.0) { + viewDist = abs(getViewZ(closestTexel)); + fogFactor = smoothstep(uFogNear, uFogFar, viewDist); + if (!uTransparentBackground) { + color.rgb = mix(color.rgb, uFogColor, fogFactor); + } else { color.a = 1.0 - fogFactor; } - color.rgb = mix(color.rgb, uFogColor, fogFactor); } #endif @@ -124,8 +118,14 @@ void main(void) { #ifdef dOcclusionEnable float depth = getDepth(coords); if (!isBackground(depth)) { + viewDist = abs(getViewZ(depth)); + fogFactor = smoothstep(uFogNear, uFogFar, viewDist); float occlusionFactor = getSsao(coords); - color = mix(occlusionColor, color, occlusionFactor); + if (!uTransparentBackground) { + color.rgb = mix(mix(occlusionColor, uFogColor, fogFactor), color.rgb, occlusionFactor); + } else { + color.rgb = mix(occlusionColor * (1.0 - fogFactor), color.rgb, occlusionFactor); + } } #endif diff --git a/src/mol-gl/shader/spheres.frag.ts b/src/mol-gl/shader/spheres.frag.ts index 120a0d6e3a004cc68f147a3fcb8b90f655f82af5..6f1c2ba1415a6f21b33b2382f89c7a5b86a88f43 100644 --- a/src/mol-gl/shader/spheres.frag.ts +++ b/src/mol-gl/shader/spheres.frag.ts @@ -15,9 +15,6 @@ precision highp int; #include common_clip #include wboit_params -uniform float uClipNear; -uniform float uIsOrtho; - varying float vRadius; varying float vRadiusSq; varying vec3 vPoint; @@ -98,9 +95,9 @@ void main(void){ #include apply_interior_color #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragDepthEXT; + #include apply_fog #include wboit_write #endif } diff --git a/src/mol-gl/shader/ssao-blur.frag.ts b/src/mol-gl/shader/ssao-blur.frag.ts index ace3593d5f54e0036c3b8735ed6fa63edbae18b7..93c0041b78038592b6aa0bd7e72be0714c20d28c 100644 --- a/src/mol-gl/shader/ssao-blur.frag.ts +++ b/src/mol-gl/shader/ssao-blur.frag.ts @@ -24,14 +24,6 @@ uniform float uFar; #include common -float perspectiveDepthToViewZ(const in float invClipZ, const in float near, const in float far) { - return (near * far) / ((far - near) * invClipZ - far); -} - -float orthographicDepthToViewZ(const in float linearClipZ, const in float near, const in float far) { - return linearClipZ * (near - far) - near; -} - float getViewZ(const in float depth) { #if dOrthographic == 1 return orthographicDepthToViewZ(depth, uNear, uFar); @@ -47,7 +39,7 @@ bool isBackground(const in float depth) { void main(void) { vec2 coords = gl_FragCoord.xy / uTexSize; - vec2 packedDepth = texture(tSsaoDepth, coords).zw; + vec2 packedDepth = texture2D(tSsaoDepth, coords).zw; float selfDepth = unpackRGToUnitInterval(packedDepth); // if background and if second pass @@ -66,27 +58,27 @@ void main(void) { for (int i = -dOcclusionKernelSize / 2; i <= dOcclusionKernelSize / 2; i++) { vec2 sampleCoords = coords + float(i) * offset; - vec4 sampleSsaoDepth = texture(tSsaoDepth, sampleCoords); + vec4 sampleSsaoDepth = texture2D(tSsaoDepth, sampleCoords); float sampleDepth = unpackRGToUnitInterval(sampleSsaoDepth.zw); if (isBackground(sampleDepth)) { continue; } - if (abs(i) > 1) { + if (abs(float(i)) > 1.0) { // abs is not defined for int in webgl1 float sampleViewZ = getViewZ(sampleDepth); if (abs(selfViewZ - sampleViewZ) > uMaxPossibleViewZDiff) { continue; } } - float kernel = uKernel[abs(i)]; + float kernel = uKernel[int(abs(float(i)))]; // abs is not defined for int in webgl1 float sampleValue = unpackRGToUnitInterval(sampleSsaoDepth.xy); sum += kernel * sampleValue; kernelSum += kernel; } - + gl_FragColor = vec4(packUnitIntervalToRG(sum / kernelSum), packedDepth); } `; \ No newline at end of file diff --git a/src/mol-gl/shader/text.frag.ts b/src/mol-gl/shader/text.frag.ts index 0f3659f77a5848970e5fe85b537534478c604f1a..d6eb9a243588cacf7f2c022f54458b20f81d0cc7 100644 --- a/src/mol-gl/shader/text.frag.ts +++ b/src/mol-gl/shader/text.frag.ts @@ -65,10 +65,10 @@ void main(){ gl_FragColor = material; #elif defined(dRenderVariant_color) #include apply_marker_color - #include apply_fog float fragmentDepth = gl_FragCoord.z; bool interior = false; + #include apply_fog #include wboit_write #endif }