Deep conflict
Two overlapping models, through browser rotation preview, will find that the model will flicker when rotating.
In this case, the two models overlap, and the computer cannot tell who is in front and who is behind. This situation can be understood as a deep conflict Z-fighting
.
function addBox() {<!-- --> const geometry = new THREE. BoxGeometry(10, 10, 10); // material const material = new THREE. MeshPhysicalMaterial({<!-- --> color: 0x51efe4, //0x51efe4 sets the material color }); // network model 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); }
Effect:
The distance between the two geometric Mesh
Appropriate offset to solve the depth conflict, the offset size is relatively small compared to the model size, and the visual approximation of the two geometric bodies is still a coincidence effect.
mesh2.position.z = 1;
The webgl renderer sets the logarithmic depth buffer
I have encountered this kind of situation here once, and after zooming in and out after compressing the model, I will find a bug that the model flickers, so here you can use logarithmicDepthBuffer
to solve the conflict problem.
Note: If the gap between the two model surfaces is too small, or coincident, the logarithmic depth buffer of this renderer has no effect
// WebGL renderer settings const renderer = new THREE. WebGLRenderer({<!-- --> // Set the logarithmic depth buffer to optimize the depth conflict problem logarithmicDepthBuffer: true, });
the difference:
const geometry = new THREE. BoxGeometry(10, 10, 10); // material const material = new THREE. MeshPhysicalMaterial({<!-- --> color: 0x51efe4, //0x51efe4 sets the material color }); // network model 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; // add Y axis scene. add(mesh); scene. add(mesh2);
Do not add logarithmicDepthBuffer
Model loading progress bar
Here take GLTFLoader
to test
let loadedData = 0 loader.load(new URL(`../assets/model.glb`, import.meta.url).href, function (gltf) {<!-- --> scene. add(gltf. scene); render(); }, function (xhr) {<!-- --> // Print in the background to view the loading progress of the model file // console.log("Percentage of loading completed" + (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("Loading error occurred"); } );
You can judge here, if loadedData
is equal to 100, that is, when the model is loaded, then this text will be hidden
Attach the complete code:
/* * @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">yellow</el-button> <el-button class="green-btn" type="success" plain @click="greenBtn">green</el-button> <el-button class="save-btn" @click="saveFile">Download</el-button> <div class="container" ref="container"></div> </template> <script setup> import * as THREE from "three"; // track 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"; // three required parameters let scene, camera, renderer, controls, mesh, material, group, texture, gui, textureCube; onMounted(() => {<!-- --> // The outer layer needs to get the dom element and the width and height of the browser to set the length and width of the canvas // clientWidth is equivalent to container.value.clientWidth let container = document. querySelector(". container"); const {<!-- --> clientWidth, clientHeight } = container; console.log(clientHeight); // First you need to get the scene, here the public method is placed in the init function const init = () => {<!-- --> scene = new THREE. Scene(); // set a background for the camera scene.background = new THREE.Color(0xaaaaaa); // perspective projection camera PerspectiveCamera // Supported parameters: fov, aspect, near, far camera = new THREE. PerspectiveCamera( 60, clientWidth / clientHeight, 0.001, 6000 ); // camera coordinates camera.position.set(30, 30, 30); // The camera observes the target camera. lookAt(scene. position); // Renderer renderer = new THREE. WebGLRenderer({<!-- --> antialias: true, preserveDrawingBuffer: true, logarithmicDepthBuffer: true }); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // how big to render 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("View the current screen device pixel ratio", 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); // material const material = new THREE. MeshPhysicalMaterial({<!-- --> color: 0x51efe4, //0x51efe4 sets the material color }); // network model 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); } // camera controls const control = () => {<!-- --> controls = new OrbitControls(camera, renderer.domElement); controls.addEventListener("change", function () {<!-- -->}); }; control(); // light source const linght = () => {<!-- --> const pointLight = new THREE. PointLight(0xffffff, 1.0); // pointLight.position.set(400, 0, 0);//The point light source is placed on the x-axis pointLight.position.set(100, 60, 50); //Set the position of the light source // The light source and the mesh model Mesh are part of the 3D scene, and naturally need to be added to the 3D scene to work. scene.add(pointLight); // add light to the scene /* 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", () => {<!-- --> // update camera 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"); // Through the hyperlink herf attribute, set the data to be saved to the file var canvas = renderer.domElement; //Get the canvas object link.href = canvas.toDataURL("image/png"); link.download = "threejs.png"; //Download file name link.click(); //js code triggers the mouse click event of hyperlink element a, and starts to download the file to the local // Through the hyperlink herf attribute, set the data to be saved to the file // link.href = window.URL.createObjectURL(new Blob([JSON.stringify(scene),JSON.stringify(mesh)])); // link.download = 'model data.txt';//download file name // link.download = 'threejs.png'; // const canvas = renderer.domElement; //Get the canvas object // link.href = canvas.toDataURL("image/png"); // link.click();//js code triggers the mouse click event of hyperlink element a, and starts to download the file to the local }; </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>