From 667717bad86e4eb394b4dd6059a8361fcf5ae166 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Mon, 19 Nov 2018 17:01:23 -0800 Subject: [PATCH] added clipping and fog support --- src/mol-canvas3d/canvas3d.ts | 74 ++++++++++--------- .../helper/bounding-sphere-helper.ts | 2 +- src/mol-geo/geometry/geometry.ts | 2 +- src/mol-geo/geometry/mesh/mesh.ts | 2 +- src/mol-gl/renderer.ts | 11 +-- src/mol-gl/shader/chunks/apply-fog.glsl | 4 + 6 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index 616c6b8b9..0e351df9b 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -29,16 +29,19 @@ import { Camera } from './camera'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { BoundingSphereHelper } from './helper/bounding-sphere-helper'; -export const Canvas3DParams: PD.Params = { +export const Canvas3DParams = { // TODO: FPS cap? // maxFps: PD.Numeric(30), - cameraPosition: PD.Vec3(Vec3.create(0, 0, 50)), // TODO or should it be in a seperate 'state' property? - pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }), - backgroundColor: PD.Color(Color(0x000000)), cameraMode: PD.Select('perspective', [['perspective', 'Perspective'], ['orthographic', 'Orthographic']]), - showBoundingSpheres: PD.Boolean(true, { description: 'Show bounding spheres of render objects.' }), + backgroundColor: PD.Color(Color(0x000000)), + clipNear: PD.Numeric(1, { min: 1, max: 100, step: 1 }), + clipFar: PD.Numeric(100, { min: 1, max: 100, step: 1 }), + fogNear: PD.Numeric(50, { min: 1, max: 100, step: 1 }), + fogFar: PD.Numeric(100, { min: 1, max: 100, step: 1 }), + pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }), + showBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of render objects.' }), // debug: PD.Group({ - // showBoundingSpheres: PD.Boolean(true, { description: 'Show bounding spheres of render objects.' }), + // showBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of render objects.' }), // }) } export type Canvas3DParams = typeof Canvas3DParams @@ -96,7 +99,7 @@ namespace Canvas3D { const camera = new Camera({ near: 0.1, far: 10000, - position: Vec3.clone(p.cameraPosition), + position: Vec3.create(0, 0, 10), mode: p.cameraMode }) @@ -158,38 +161,33 @@ namespace Canvas3D { } } - // let nearPlaneDelta = 0 - // function computeNearDistance() { - // const focusRadius = scene.boundingSphere.radius - // let dist = Vec3.distance(controls.target, camera.position) - // if (dist > focusRadius) return dist - focusRadius - // return 0 - // } - - function render(variant: RenderVariant, force: boolean) { - if (isPicking) return false - // const p = scene.boundingSphere.center - // console.log(p[0], p[1], p[2]) - // Vec3.set(controls.target, p[0], p[1], p[2]) + let currentNear = -1, currentFar = -1, currentFogNear = -1, currentFogFar = -1 + function setClipping() { + const cDist = Vec3.distance(camera.state.position, camera.state.target) + const bRadius = Math.max(10, scene.boundingSphere.radius) - // TODO update near/far - // const focusRadius = scene.boundingSphere.radius - // const targetDistance = Vec3.distance(controls.target, camera.position) - // console.log(targetDistance, controls.target, camera.position) - // let near = computeNearDistance() + nearPlaneDelta - // camera.near = Math.max(0.01, Math.min(near, targetDistance - 0.5)) + const nearFactor = (50 - p.clipNear) / 50 + const farFactor = -(50 - p.clipFar) / 50 + const near = cDist - (bRadius * nearFactor) + const far = cDist + (bRadius * farFactor) - // let fogNear = targetDistance - camera.near + 1 * focusRadius - nearPlaneDelta; - // let fogFar = targetDistance - camera.near + 2 * focusRadius - nearPlaneDelta; + const fogNearFactor = (50 - p.fogNear) / 50 + const fogFarFactor = -(50 - p.fogFar) / 50 + const fogNear = cDist - (bRadius * fogNearFactor) + const fogFar = cDist + (bRadius * fogFarFactor) - // // console.log(fogNear, fogFar); - // camera.fogNear = Math.max(fogNear, 0.1); - // camera.fogFar = Math.max(fogFar, 0.2); + if (near !== currentNear || far !== currentFar || fogNear !== currentFogNear || fogFar !== currentFogFar) { + camera.setState({ near, far, fogNear, fogFar }) + currentNear = near, currentFar = far, currentFogNear = fogNear, currentFogFar = fogFar + } + } - // console.log(camera.fogNear, camera.fogFar, targetDistance) + function render(variant: RenderVariant, force: boolean) { + if (isPicking) return false let didRender = false controls.update() + setClipping() const cameraChanged = camera.updateMatrices(); if (force || cameraChanged) { @@ -334,6 +332,7 @@ namespace Canvas3D { reprCount.next(reprRenderObjects.size) boundingSphereHelper.update() scene.update() + requestDraw(true) } }, update: () => scene.update(), @@ -375,6 +374,12 @@ namespace Canvas3D { if (props.backgroundColor !== undefined && props.backgroundColor !== renderer.props.clearColor) { renderer.setClearColor(props.backgroundColor) } + + if (props.clipNear !== undefined) p.clipNear = props.clipNear + if (props.clipFar !== undefined) p.clipFar = props.clipFar + if (props.fogNear !== undefined) p.fogNear = props.fogNear + if (props.fogFar !== undefined) p.fogFar = props.fogFar + if (props.pickingAlphaThreshold !== undefined && props.pickingAlphaThreshold !== renderer.props.pickingAlphaThreshold) { renderer.setPickingAlphaThreshold(props.pickingAlphaThreshold) } @@ -386,9 +391,12 @@ namespace Canvas3D { get props() { return { - cameraPosition: Vec3.clone(camera.position), cameraMode: camera.state.mode, backgroundColor: renderer.props.clearColor, + clipNear: p.clipNear, + clipFar: p.clipFar, + fogNear: p.fogNear, + fogFar: p.fogFar, pickingAlphaThreshold: renderer.props.pickingAlphaThreshold, showBoundingSpheres: boundingSphereHelper.visible } diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts index 2b7d43616..b3fbe849e 100644 --- a/src/mol-canvas3d/helper/bounding-sphere-helper.ts +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -19,7 +19,7 @@ export class BoundingSphereHelper { constructor(private scene: Scene, visible: boolean) { const builder = MeshBuilder.create(1024, 512) this.mesh = builder.getMesh() - const values = Mesh.createValuesSimple(this.mesh, { alpha: 0.1 }) + const values = Mesh.createValuesSimple(this.mesh, { alpha: 0.1, doubleSided: false }) this.renderObject = createMeshRenderObject(values, { visible, pickable: false }) scene.add(this.renderObject) } diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index 7612971c9..eee463dc1 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -62,7 +62,7 @@ export namespace Geometry { export const Params = { alpha: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }, { label: 'Opacity' }), - useFog: PD.Boolean(false), + useFog: PD.Boolean(true), highlightColor: PD.Color(Color.fromNormalizedRgb(1.0, 0.4, 0.6)), selectColor: PD.Color(Color.fromNormalizedRgb(0.2, 1.0, 0.1)), diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts index d3c44ab60..6d4b450d4 100644 --- a/src/mol-geo/geometry/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -343,7 +343,7 @@ export namespace Mesh { export const Params = { ...Geometry.Params, - doubleSided: PD.Boolean(false), + doubleSided: PD.Boolean(true), flipSided: PD.Boolean(false), flatShaded: PD.Boolean(false), } diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index aee976db3..039ef5be8 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -68,6 +68,7 @@ namespace Renderer { clearColor = color const [ r, g, b ] = Color.toRgbNormalized(color) gl.clearColor(r, g, b, 1.0) + Vec3.set(fogColor, r, g, b) } setClearColor(clearColor) @@ -94,12 +95,12 @@ namespace Renderer { uViewportHeight: ValueCell.create(viewport.height), uViewport: ValueCell.create(viewportVec4), - uLightColor: ValueCell.create(Vec3.clone(lightColor)), - uLightAmbient: ValueCell.create(Vec3.clone(lightAmbient)), + uLightColor: ValueCell.create(lightColor), + uLightAmbient: ValueCell.create(lightAmbient), - uFogNear: ValueCell.create(camera.state.near), - uFogFar: ValueCell.create(camera.state.far / 50), - uFogColor: ValueCell.create(Vec3.clone(fogColor)), + uFogNear: ValueCell.create(camera.state.fogNear), + uFogFar: ValueCell.create(camera.state.fogFar), + uFogColor: ValueCell.create(fogColor), uPickingAlphaThreshold: ValueCell.create(pickingAlphaThreshold), } diff --git a/src/mol-gl/shader/chunks/apply-fog.glsl b/src/mol-gl/shader/chunks/apply-fog.glsl index 0dcfbd63f..a0f273ebc 100644 --- a/src/mol-gl/shader/chunks/apply-fog.glsl +++ b/src/mol-gl/shader/chunks/apply-fog.glsl @@ -3,4 +3,8 @@ // float depth = gl_FragCoord.z / gl_FragCoord.w; float fogFactor = smoothstep(uFogNear, uFogFar, depth); gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor); + float alpha = (1.0 - fogFactor) * gl_FragColor.a; + if (alpha < 0.01) + discard; + gl_FragColor = vec4( gl_FragColor.rgb, alpha ); #endif \ No newline at end of file -- GitLab