Threejs - 14. À propos des conflits profonds, des chevauchements et de la mise en œuvre de l'effet de la barre de progression du modèle de chargement (code complet joint)

conflit profond

Pour deux modèles qui se chevauchent, si vous prévisualisez le modèle en le faisant pivoter via le navigateur, vous constaterez que le modèle scintille lors de sa rotation.
Dans ce cas, la raison principale est que les deux modèles se chevauchent et que l'ordinateur ne peut pas dire qui est devant et qui est derrière. Cette situation peut être comprise comme un conflit profond 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);
}

Effet:
Veuillez ajouter une description en image

Distance de maillage entre deux entités géométriques

Un décalage approprié peut résoudre le conflit de profondeur. La taille du décalage est relativement petite par rapport à la taille du modèle. Visuellement, les deux géométries se rapprochent toujours de l'effet de chevauchement.

mesh2.position.z = 1;

Veuillez ajouter une description en image

Le moteur de rendu Webgl définit un tampon de profondeur logarithmique

J'ai rencontré cette situation ici une fois. En compressant le modèle puis en effectuant un zoom avant et arrière, vous découvrirez un bug de scintillement du modèle, vous pourrez donc utiliser cette méthode pour résoudre logarithmicDepthBufferle problème de conflit.
Remarque : Si l'écart entre les deux surfaces du modèle est trop petit ou se chevauche, le tampon de profondeur logarithmique de ce moteur de rendu n'aura aucun effet.

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

la différence:

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);

Veuillez ajouter une description en image

Ne pas ajouterlogarithmicDepthBuffer
Veuillez ajouter une description en image

Barre de progression du chargement du modèle

GLTFLoaderObtenez-le ici pour tester

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("加载发生错误");
    }
  );

Vous pouvez porter un jugement ici. S'il loadedDataest égal à 100, c'est-à-dire au chargement du modèle, alors ce texte sera masqué.
Le code complet est joint :

/*
 * @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>


Je suppose que tu aimes

Origine blog.csdn.net/nanchen_J/article/details/131759611
conseillé
Classement