因为该项目比较复杂庞大,在此就简单介绍一下:
通过Three.js创建若干个物体进行了组装,从而形成了一个类似眼球模拟模型的项目,用户可以通过拖动鼠标来达到控制视角(摄像机)的目的,以此来观察整个眼球状态。
左视该眼球可以看到红色的圆形平面,但是左视则发现红色平面消失。
创建外部白色球体、内部蓝色不规则球体、红色平面代码:
createSphere() { const radius = 2.2; const outerGeometry = new THREE.SphereGeometry(radius, 120, 120); const outerMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff, // 定义外部的球为白色 transparent: true, opacity: 0.6, // 降低不透明度以减少反射 metalness: 0.5, roughness: 0.3, }); const outerSphere = new THREE.Mesh(outerGeometry, outerMaterial); // 创建一个具有水平曲面的不完全球体 const waterSurfaceGeometry = new THREE.CircleGeometry(radius - 0.1) const innerGeometry = new THREE.SphereGeometry( radius - 0.1, 240, 240, 0, 2 * Math.PI, Math.PI, Math.PI / 2 ); const innerMaterial = new THREE.MeshPhongMaterial({ color: 0x02c0f5, // 定义内部的球体为蓝色 opacity: 1, metalness: 0.5, roughness: 0.3, }); const waterSurfaceMaterial = new THREE.MeshPhongMaterial({ color: 0xf60404, // 定义去曲面水面为红色 opacity: 1, transparent:false, // 设置成不透明 metalness: 0.5, roughness: 0.3, }); const innerSphere = new THREE.Mesh(innerGeometry, innerMaterial); const waterSurface = new THREE.Mesh(waterSurfaceGeometry, waterSurfaceMaterial) innerSphere.scale.set(1, 1, 1); innerSphere.add(waterSurface) this.outerSphere = outerSphere; this.innerSphere = innerSphere; const sphereGroup = new THREE.Group(); sphereGroup.add(outerSphere); sphereGroup.add(innerSphere); this.sphere = sphereGroup; this.innerSphere = innerSphere; return sphereGroup; },
很明显,上面四种解决方案都不可行,首先红色平面的transparent
属性为false,并且不透明度也为1;其次肯定不是光照问题,因为白色外部球体和蓝色内部球体都能正常显示;最后更不是摄像机位置问题,无论怎么调整方位都不能显示出红色圆形。
因此我们需要使用双面渲染,双面渲染能够确保从内部看到外部的表面。默认情况下,Three.js 只会渲染面的正面,通过启用 side: THREE.DoubleSide 可以使其渲染双面。
所以我们只需要在上面的代码中添加一行就能解决这个问题。
const waterSurfaceMaterial = new THREE.MeshPhongMaterial({ color: 0xf60404, // 定义去曲面水面为红色 opacity: 1, transparent:false, // 设置成不透明 metalness: 0.5, roughness: 0.3, side: THREE.DoubleSide // 允许双面渲染 });
最后我们来看看效果!!