首页 > 其他分享 >Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)

Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)

时间:2024-01-07 14:31:41浏览次数:30  
标签:Threejs const 进度条 material THREE mesh2 mesh new 加载

深度冲突

两个模型重叠的模型,通过浏览器旋转预览,会发现模型旋转的时候会发生闪烁。 这种情况,主要是两个模型重合,电脑分不清谁在前谁在后,这种情况,可以理解为深度冲突Z-fighting

function addBox() {
  const geometry = new THREE.BoxGeometry(10, 10, 10);
  // 材质
  const material = new THREE.MeshPhysicalMaterial({
    color: 0x51efe4, //0x51efe4设置材质颜色
  });
  // 网络模型
  mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(0, 10, 0);
  const mesh2 = mesh.clone();
  mesh2.geometry = mesh.geometry.clone();
  mesh2.material = mesh.material.clone();
  mesh2.position.x = 5;
  mesh2.material.color.set(0xffff00);
  scene.add(mesh);
  scene.add(mesh2);
}

效果:

Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)_超链接

两个几何体 Mesh 拉开距离

适当偏移,解决深度冲突,偏移尺寸相对模型尺寸比较小,视觉上两个几何体近似还是重合效果。

mesh2.position.z = 1;

Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)_加载_02

webgl 渲染器设置对数深度缓冲区

这种情况我这里遇到过一次,通过压缩模型后进行放大缩小会发现出现模型闪烁的 bug,所以这里可以用logarithmicDepthBuffer解决冲突问题。 注意:如果两模型面间隙过小,或者重合,,此渲染器对数深度缓冲区也是没有效果的

// WebGL渲染器设置
const renderer = new THREE.WebGLRenderer({
  // 设置对数深度缓冲区,优化深度冲突问题
  logarithmicDepthBuffer: true,
});

区别:

const geometry = new THREE.BoxGeometry(10, 10, 10);
// 材质
const material = new THREE.MeshPhysicalMaterial({
  color: 0x51efe4, //0x51efe4设置材质颜色
});
// 网络模型
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 10, 0);
const mesh2 = mesh.clone();
mesh2.geometry = mesh.geometry.clone();
mesh2.material = mesh.material.clone();
mesh2.position.x = 5;
mesh2.material.color.set(0xffff00);
mesh2.position.z = 1;
mesh.position.y = 10.01;  // 加Y轴
scene.add(mesh);
scene.add(mesh2);

Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)_加载_03

不加logarithmicDepthBuffer

Threejs——十四、关于深度冲突、重叠、以及加载模型进度条效果实现(附完整代码)_超链接_04

模型加载进度条

这里拿GLTFLoader来测试

let loadedData = 0
loader.load(new URL(`../assets/model.glb`, import.meta.url).href,function (gltf) {
      scene.add(gltf.scene);
      render();
    },
    function (xhr) {
      // 后台打印查看模型文件加载进度
    //   console.log("加载完成的百分比" + (xhr.loaded / xhr.total) * 100 + "%");
      loadedData = Math.floor((xhr.loaded / xhr.total) * 100);
    //   console.log(Math.floor((xhr.loaded / xhr.total) * 100));
      if (Math.floor((xhr.loaded / xhr.total) * 100) == 100) {
        setTimeout(() => {
          data.statu = false;
        }, 1000);
      }
    },
    function (err) {
      console.error("加载发生错误");
    }
  );

这里可以进行判断,如果loadedData等于100,也就是模型加载完毕的时候,那么这段文字就隐藏起来 附完整代码:

/*
 * @Author: SouthernWind 
 * @Date: 2023-06-14 16:38:59 
 * @Last Modified by: SouthernWind 
 * @Last Modified time: 2023-06-20 14:39:07
 */

<template>
  <el-button class="yellow-btn" type="warning" plain @click="yellowBtn">黄色</el-button>
  <el-button class="green-btn" type="success" plain @click="greenBtn">绿色</el-button>
  <el-button class="save-btn" @click="saveFile">下载</el-button>
  <div class="container" ref="container"></div>
</template>

<script setup>
import * as THREE from "three";
// 轨道
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";

import { ref, reactive, onMounted } from "vue";
// 三个必备的参数
let scene,
  camera,
  renderer,
  controls,
  mesh,
  material,
  group,
  texture,
  gui,
  textureCube;

onMounted(() => {
  // 外层需要获取到dom元素以及浏览器宽高,来对画布设置长宽
  // clientWidth等同于container.value.clientWidth
  let container = document.querySelector(".container");
  const { clientWidth, clientHeight } = container;
  console.log(clientHeight);
  // 首先需要获取场景,这里公共方法放在init函数中
  const init = () => {
    scene = new THREE.Scene();
    // 给相机设置一个背景
    scene.background = new THREE.Color(0xaaaaaa);
    // 透视投影相机PerspectiveCamera
    // 支持的参数:fov, aspect, near, far
    camera = new THREE.PerspectiveCamera(
      60,
      clientWidth / clientHeight,
      0.001,
      6000
    );
    // 相机坐标
    camera.position.set(30, 30, 30);

    // 相机观察目标
    camera.lookAt(scene.position);
    // 渲染器
    renderer = new THREE.WebGLRenderer({
      antialias: true,
      preserveDrawingBuffer: true,
      logarithmicDepthBuffer: true
    });
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    // 渲染多大的地方
    renderer.setClearAlpha(0.0);
    renderer.setSize(clientWidth, clientHeight);
    /* renderer.outputEncoding = THREE.sRGBEncoding; */
    // const axesHelper = new THREE.AxesHelper(150);
    // scene.add(axesHelper);
    container.appendChild(renderer.domElement);
    addBox();
    console.log("查看当前屏幕设备像素比", window.devicePixelRatio);
  };
  init();
  function addBox() {
    /* gui = new GUI();
    const geometry = new THREE.TorusKnotGeometry(10, 3, 100, 16);
    const material = new THREE.MeshPhysicalMaterial({
      color: 0x30cff8,
      metalness: 0,
      roughness: 0,
      transmission: 0.5,
      ior: 1.5,
    });
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
    gui.add(material, "transmission", 0, 1);
    gui.add(material, "ior", 1, 2.333); */

    const geometry = new THREE.BoxGeometry(10, 10, 10);
    // 材质
    const material = new THREE.MeshPhysicalMaterial({
      color: 0x51efe4, //0x51efe4设置材质颜色
    });
    // 网络模型
    mesh = new THREE.Mesh(geometry, material);
    mesh.position.set(0, 10, 0);
    const mesh2 = mesh.clone();
    mesh2.geometry = mesh.geometry.clone();
    mesh2.material = mesh.material.clone();
    mesh2.position.x = 5;
    mesh2.material.color.set(0xffff00);
    mesh2.position.z = 1;
    mesh.position.y = 10.01;
    scene.add(mesh);
    scene.add(mesh2);
    // camera.position.set(292*5, 223*5, 185*5);
  }

  // 相机控件
  const control = () => {
    controls = new OrbitControls(camera, renderer.domElement);
    controls.addEventListener("change", function () {});
  };
  control();

  // 光源
  const linght = () => {
    const pointLight = new THREE.PointLight(0xffffff, 1.0);
    // pointLight.position.set(400, 0, 0);//点光源放在x轴上
    pointLight.position.set(100, 60, 50); //设置光源的位置
    // 光源和网格模型Mesh对应一样是三维场景的一部分,自然需要添加到三维场景中才能起作用。
    scene.add(pointLight); // 添加光源到场景中

    /*  const pointLight = new THREE.AmbientLight(0xffffff, 1.0);
    pointLight.position.set(150, 150, 150);
        scene.add(pointLight); */
    const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
    scene.add(pointLightHelper);
  };
  linght();
  const render = () => {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  };
  render();
  window.addEventListener("resize", () => {
    // 更新摄像头
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  });
});
const yellowBtn = () => {
  console.log(mesh);
  mesh.material.color.set(0xe5a144);
};
const greenBtn = () => {
  console.log(mesh);
  mesh.material.color.set(0x69c242);
};
const saveFile = () => {
  const link = document.createElement("a");
  // 通过超链接herf属性,设置要保存到文件中的数据
  var canvas = renderer.domElement; //获取canvas对象
  link.href = canvas.toDataURL("image/png");
  link.download = "threejs.png"; //下载文件名
  link.click(); //js代码触发超链接元素a的鼠标点击事件,开始下载文件到本地

  // 通过超链接herf属性,设置要保存到文件中的数据
  // link.href = window.URL.createObjectURL(new Blob([JSON.stringify(scene),JSON.stringify(mesh)]));
  // link.download = '模型数据.txt';//下载文件名
  // link.download = 'threejs.png';
  // const canvas = renderer.domElement; //获取canvas对象
  // link.href = canvas.toDataURL("image/png");
  // link.click();//js代码触发超链接元素a的鼠标点击事件,开始下载文件到本地
};
</script>

<style>
.container {
  width: 100%;
  height: 100vh;
  position: relative;
  z-index: 1;
  /* background: #ff5810; */
}
.yellow-btn {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 99;
}
.green-btn {
  position: absolute;
  top: 0;
  left: 50px;
  z-index: 99;
}
.save-btn {
  position: absolute;
  top: 0;
  left: 111px;
  z-index: 99;
}
</style>

标签:Threejs,const,进度条,material,THREE,mesh2,mesh,new,加载
From: https://blog.51cto.com/u_15947040/9134097

相关文章

  • slf4j+logback源码加载流程解析
    slf4j绑定logback源码解析Loggerlog=LoggerFactory.getLogger(LogbackDemo.class);如上述代码所示,在项目中通常会这样创建一个Logger对象去打印日志。然后点进去,会走到LoggerFactory的getILoggerFactory()方法,如下代码所示。publicstaticILoggerFactorygetILoggerFactory()......
  • mac下appium定位元素检察器会话在启动会话后,界面一直在加载中
    1.检查Appium服务器是否正常运行,可以在终端中输入appium查看是否正常启动;2.检查手机是否正常连接,可以在终端中输入idevice_id-l查看是否有设备连接;3.检查Appium服务器和手机之间的连接,可以在终端中输入ideviceinfo-u<device_udid>查看是否有设备连接;4.检查Appium服务器......
  • 鸿蒙原生应用/元服务开发-发布进度条类型通知
    进度条通知也是常见的通知类型,主要应用于文件下载、事务处理进度显示。HarmonyOS提供了进度条模板,发布通知应用设置好进度条模板的属性值,如模板名、模板数据,通过通知子系统发送到通知栏显示。目前系统模板仅支持进度条模板,通知模板NotificationTemplate中的data参数为用户自定义数......
  • 无涯教程-jsoup - 加载文件
    以下示例将从本地文件加载HTML文件,返回一个Document文档,然后查找其数据。Fileinput=newFile(xxxxx);Documentdocument=Jsoup.parse(input,"UTF-8");Jsoup.parse示例使用您选择的任何编辑器在C:/>jsoup中创建以下Java程序。JsoupTester.javaimportjava.io.File;impo......
  • 小程序更新版本(加载首页onLoad的时候调用)
    /***获取新版本信息*/exportfunctiongetNewVersionUpdateMessage(){console.log('版本更新!')constupdateManager=uni.getUpdateManager();updateManager.onCheckForUpdate(function(res){//请求完新版本信息的回调console.log(res.hasUpdate);......
  • 亚信安慧AntDB数据并行加载工具的实现(一)
    1.概述数据加载速度是评判数据库性能的重要指标,能否提高数据加载速度,对文件数据进行并行解析,直接影响数据库运维管理效率。基于此,AntDB分布式数据库提供了两种数据加载方式:一是类似于PostgreSQL的Copy命令,二是通过AntDB提供的并行加载工具。Copy命令是大家都比较熟悉的,但Copy命令导......
  • 亚信安慧AntDB数据并行加载工具的实现(二)
    3.功能性说明本节对并行加载工具的部分支持的功能进行简要说明。1)支持表类型并行加载工具支持普通表、分区表。2)支持指定导入字段文件中并不是必须包含表中所有的字段,用户可以指定导入某些字段,但是指定的字段数要和文件中的字段数保持一致。3)支持导入部分记录并行加载工具支......
  • Java 自定义类加载器
    1. 系统类加载器系统提供的类加载器有如下三种:启动类加载器, 扩展类加载器,引用程序类加载器。1.1 启动类加载器启动类加载器(BootstrapClassLoader)负责将存放在<JRE_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar......
  • Cesium常用数据类型加载方式
    WMTSlettdtIMGLabel=newCesium.WebMapTileServiceImageryProvider({//影像注记url:"http://t{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatr......
  • 【Java】一文讲解Java类加载机制
    Java类加载机制是Java运行时的核心组成部分,负责在程序运行过程中动态加载和连接类文件,并将其转换为可执行代码。理解类加载机制,能更容易理解你一行行敲下的Java代码是如何在JVM虚拟机上运行起来。并且理解类加载机制之后,我们也能掌握如何自定义类加载器,如何做热更新等。//准......