Three.js加载Sketchfab模型出现渲染色差的问题求助
Three.js加载Sketchfab模型出现渲染色差的问题求助
我最近在尝试展示从Sketchfab下载的模型,但用Three.js渲染出来的效果和预期的差很多,想请教下问题出在哪,是模型本身的问题还是我的Three.js代码设置有问题?
预期渲染效果

我的Three.js渲染效果

想问问怎么才能达到第一张图的效果?问题是在模型上还是我的Three.js展示方式上?
以下是我的代码:
import * as THREE from 'three'; import { GLTFLoader } from 'https://unpkg.com/three@0.138.3/examples/jsm/loaders/GLTFLoader.js'; import { FBXLoader } from 'https://unpkg.com/three@0.138.3/examples/jsm/loaders/FBXLoader.js'; import { OrbitControls } from 'https://unpkg.com/three@0.138.3/examples/jsm/controls/OrbitControls.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 10000 ); camera.position.set( -50, 50, 1000 ); camera.lookAt(0, 0, 0) const renderer = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true}); renderer.setSize( window.innerWidth, window.innerHeight); const color = 0xFFFFFF; const intensity = 10; const light = new THREE.DirectionalLight(color, intensity); light.position.set(-60, 60, 1060); // 测试立方体 const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); document.getElementById("threejsbackdrop").appendChild( renderer.domElement ); const controls = new OrbitControls( camera, renderer.domElement ); controls.update(); const loader = new GLTFLoader(); loader.load('./black_hole.glb', function ( gltf ) { gltf.scene.receiveShadow = true; scene.add( gltf.scene ); }, function ( xhr ) { if(( xhr.loaded / xhr.total * 100 ) == 100){ console.log("Finished Loading!") } }, function ( error ) { console.log(error) console.log( 'An error happened' ); }); function animate() { requestAnimationFrame( animate ); controls.update(); renderer.render( scene, camera ); }; animate();
我的分析和解决建议
兄弟,我看了你的问题和代码,大概率是Three.js的渲染设置没跟上,不是模型的问题~ Sketchfab的预览效果是用了专业的光照环境和渲染参数的,你的代码里很多关键设置都没做,我给你梳理下问题点和修改方案:
1. 光照系统太单薄
你只用了一盏方向光,而且没有开启阴影,Sketchfab的预览通常有丰富的环境光、补光甚至HDR环境贴图,这会直接影响材质的质感和颜色表现。
2. 渲染器缺少关键设置
你没开启阴影映射、伽马校正、色调映射,这些都是让颜色和质感贴近真实预览的核心设置。
3. 相机位置太离谱
你的相机z轴在1000的位置,离模型太远了,模型在场景里可能小到几乎看不见,这也是你觉得效果不对的原因之一。
4. 测试立方体干扰
那个绿色的小立方体没啥用,建议删掉,避免干扰你观察模型。
具体修改代码
我给你调整了代码,你可以试试:
import * as THREE from 'three'; import { GLTFLoader } from 'https://unpkg.com/three@0.138.3/examples/jsm/loaders/GLTFLoader.js'; import { OrbitControls } from 'https://unpkg.com/three@0.138.3/examples/jsm/controls/OrbitControls.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 10000 ); // 调整相机位置,离模型近一点,能看清细节 camera.position.set( -50, 50, 200 ); camera.lookAt(0, 0, 0) // 渲染器关键设置:开启阴影、伽马校正、色调映射 const renderer = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true}); renderer.setSize( window.innerWidth, window.innerHeight); // 开启阴影映射 renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔和阴影 // 伽马校正,让颜色更准确 renderer.outputEncoding = THREE.sRGBEncoding; // 色调映射,模拟真实曝光 renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.2; // 完善光照:添加环境光+方向光,都开启阴影 // 环境补光,让暗部不那么死黑 const ambientLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6); scene.add(ambientLight); // 主方向光,调整参数并开启阴影 const dirLight = new THREE.DirectionalLight(0xffffff, 1.5); dirLight.position.set(-60, 60, 100); dirLight.castShadow = true; // 设置阴影相机参数,让阴影覆盖模型范围 dirLight.shadow.camera.left = -100; dirLight.shadow.camera.right = 100; dirLight.shadow.camera.top = 100; dirLight.shadow.camera.bottom = -100; dirLight.shadow.mapSize.width = 2048; dirLight.shadow.mapSize.height = 2048; scene.add(dirLight); document.getElementById("threejsbackdrop").appendChild( renderer.domElement ); const controls = new OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; // 让镜头移动更顺滑 controls.update(); const loader = new GLTFLoader(); loader.load('./black_hole.glb', function ( gltf ) { // 给模型的 mesh 开启投射和接收阴影 gltf.scene.traverse( function( child ) { if ( child.isMesh ) { child.castShadow = true; child.receiveShadow = true; } }); scene.add( gltf.scene ); }, function ( xhr ) { if(( xhr.loaded / xhr.total * 100 ) == 100){ console.log("Finished Loading!") } }, function ( error ) { console.log(error) console.log( 'An error happened' ); }); // 监听窗口大小变化 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); function animate() { requestAnimationFrame( animate ); controls.update(); renderer.render( scene, camera ); }; animate();
额外优化建议
如果想更贴近Sketchfab的效果,可以加载一张HDR环境贴图作为场景的环境贴图,代码大概是这样:
// 加载HDR环境贴图 import { RGBELoader } from 'https://unpkg.com/three@0.138.3/examples/jsm/loaders/RGBELoader.js'; new RGBELoader() .load('你的HDR文件路径.hdr', function ( texture ) { texture.mapping = THREE.EquirectangularReflectionMapping; scene.environment = texture; scene.background = texture; });
你可以找免费的HDR贴图网站下载合适的环境贴图,效果会提升一大截~
备注:内容来源于stack exchange,提问作者user9002871




