• 一行代码解决Three.js中只能在一侧看到物体的问题


    项目场景:

      因为该项目比较复杂庞大,在此就简单介绍一下:
      通过Three.js创建若干个物体进行了组装,从而形成了一个类似眼球模拟模型的项目,用户可以通过拖动鼠标来达到控制视角(摄像机)的目的,以此来观察整个眼球状态。


    在这里插入图片描述
    Image1 Three.js眼球模型

      注:下面所说的正视为从红线正轴往瞳孔(黑色圆形)看去的视角,左视为从蓝线正轴往负轴看去,右视则与其相反

    问题描述

      左视该眼球可以看到红色的圆形平面,但是左视则发现红色平面消失。


    在这里插入图片描述
    Image2 左视可以正常看到红色的圆形

    在这里插入图片描述
    Image3 右视发现红色圆形消失



      创建外部白色球体、内部蓝色不规则球体、红色平面代码:

        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;
        },
    

    原因分析:

    1. 材质透明度问题:通过调整内部圆形的材质透明度,使其更透明,这样可以确保在摄像机视角不理想的情况下仍然能够看到内部。
    2. 光照效果:通过调整光照效果,可以改变内部圆形的明暗度,使其更加清晰可见。
    3. 内部圆形的尺寸:通过调整内部圆形的尺寸,使其在不同视角下都能够完整显示。
    4. 摄像机位置:确保摄像机的位置不会完全遮挡要显示的内容。可以尝试将摄像机向后移动或调整其位置,使其不会完全遮挡内部的圆形。

      很明显,上面四种解决方案都不可行,首先红色平面的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  // 允许双面渲染
          });
    

      最后我们来看看效果!!


    在这里插入图片描述
    Image4 右视能够正常看到红色平面

  • 相关阅读:
    什么是数字孪生?
    【halcon】踩坑unin2
    Python 多重继承时metaclass conflict问题解决与原理探究
    pytorch - storage(), stride()
    5分钟了解二叉树之LeetCode里的二叉树
    http和dubbo接口调用主动设置超时时间
    什么是分治算法?
    Python爬取天气数据并进行分析与预测
    【Linux】Linux权限
    java开源商城免费搭建 VR全景商城 saas商城 b2b2c商城 o2o商城 积分商城 秒杀商城 拼团商城 分销商城 短视频商城
  • 原文地址:https://www.cnblogs.com/hiddensharp429/p/17961962