首页 > 其他分享 >一行代码解决Three.js中只能在一侧看到物体的问题

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

时间:2024-01-13 09:33:05浏览次数:24  
标签:const 一侧 innerSphere THREE Three 圆形 红色 new 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 右视能够正常看到红色平面

标签:const,一侧,innerSphere,THREE,Three,圆形,红色,new,js
From: https://www.cnblogs.com/hiddensharp429/p/17961962

相关文章

  • js中的对象,如果赋值给多个变量,那么会有性能问题吗
    js中的对象,如果赋值给多个变量,那么会有性能问题吗?在JavaScript中,将一个对象赋值给多个变量时,并不会直接导致性能问题。当一个对象被赋值给多个变量时,实际上这些变量都会引用同一个对象,即它们指向内存中的同一块地址。这种行为称为“对象引用”。例如:constobj={a:1,b:2}......
  • js localeCompare()方法
    最后一个与模式匹配相关的字符串方法是split()。这个方法会根据传入的分隔符将字符串拆分成数组。作为分隔符的参数可以是字符串,也可以是RegExp对象。(字符串分隔符不会被这个方法当成正则表达式。)还可以传入第二个参数,即数组大小,确保返回的数组不会超过指定大小。来看下面的......
  • js-内置对象
    早期的浏览器开发商认为使用JavaScript动态生成HTML标签是一个需求。因此,早期浏览器扩展了规范,增加了辅助生成HTML标签的方法。下表总结了这些HTML方法。不过,这些方法基本上已经没有人使用了,因为结果通常不是语义化的标记。anchor(name)<aname="name">string</a>big()......
  • js eval()方法
    与encodeURI()和encodeURIComponent()相对的是decodeURI()和decodeURIComponent()。decodeURI()只对使用encodeURI()编码过的字符解码。例如,%20会被替换为空格,但%23不会被替换为井号(#),因为井号不是由encodeURI()替换的。类似地,decodeURIComponent()解码所有被encodeUR......
  • js Global 对象属性
    Global对象有很多属性,其中一些前面已经提到过了。像undefined、NaN和Infinity等特殊值都是Global对象的属性。此外,所有原生引用类型构造函数,比如Object和Function,也都是Global对象的属性。undefinedNaNInfinityObjectArrayFunctionBooleanString特殊值undefi......
  • js Math方法
    ECMAScript提供了Math对象作为保存数学公式、信息和计算的地方。Math对象提供了一些辅助计算的属性和方法。1.Math对象属性:Math对象有一些属性,主要用于保存数学中的一些特殊值。下表列出了这些属性。Math.EMath.LN10Math.LN2Math.LOG2EMath.LOG10EMath.PIMath.SQRT1_......
  • 无涯教程-JSON - Python编程
    本章介绍如何使用Python编程语言编码和解码JSON对象。让我们从准备环境开始,以使用Python进行JSON编程。在开始使用Python编码和解码JSON之前,您需要安装任何可用的JSON模块,在本教程中,我们已经下载并安装了Demjson,如下所示-$tarxvfzdemjson-1.6.tar.gz$cddemjson-1.6$pyt......
  • 无涯教程-JSON - Perl编程
    本章介绍如何使用Perl编程语言编码和解码JSON对象,让我们从准备环境开始,开始使用PerlforJSON进行编程。在使用Perl编码和解码JSON之前,需要安装JSON模块,该模块可以从CPAN获得。下载JSON-2.53.tar.gz或任何其他最新版本后,请按照以下步骤操作-$tarxvfzJSON-2.53.tar.gz$cdJSO......
  • 软件测试/测试开发全日制|Pyest结合json实现数据驱动测试
    前言数据驱动测试是提高代码覆盖率和可靠性的重要方法。结合pytest和JSON(JavaScript对象表示)文件可以轻松实现数据驱动测试。和CSV文件类似,Python读取json文件也不需要借助其他的第三方库,因此我们不需要进行额外的环境安装。下面是如何使用pytest和JSON文件进行数据驱动测试的步骤......
  • JS加密/解密之js加密小工具
    JS加密的原理和方法什么是JS加密JS加密是一种将js代码转换成不易被阅读和修改的形式的技术JS加密的目的是保护js代码的版权,防止被恶意篡改或盗用JS加密的难度和效果取决于加密算法的复杂性和安全性JS加密的常见方法压缩和混淆:将js代码的空格,换行,注释等无关字符删除,将变量名,函数名等......