Bladeren bron

added clipping and fog support

Alexander Rose 6 jaren geleden
bovenliggende
commit
667717bad8

+ 41 - 33
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
                 }

+ 1 - 1
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)
     }

+ 1 - 1
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)),
 

+ 1 - 1
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),
     }

+ 6 - 5
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),
         }

+ 4 - 0
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