如何用Three.js创建柔和灯光?新手遇对比度过锐问题
解决Three.js中GLTF模型灯光对比度锐利的问题
你当前的灯光配置导致明暗对比生硬,想要实现柔和的光影效果,需要从灯光柔化、阴影设置、补光补充这几个维度调整,具体方案如下:
1. 柔化方向光并开启软阴影
DirectionalLight默认生成硬边阴影,需开启阴影并调整参数实现柔化:
const mainLight = new THREE.DirectionalLight('white', 0.6); // 降低主光强度,避免过曝 mainLight.position.set(10, 10, 10); // 开启阴影并设置柔化参数 mainLight.castShadow = true; mainLight.shadow.mapSize.set(2048, 2048); // 提升阴影分辨率,避免模糊失真 mainLight.shadow.radius = 8; // 阴影模糊半径,值越大越柔和 mainLight.shadow.bias = -0.0001; // 修正阴影偏移导致的漏光问题 // 调整阴影相机范围,确保覆盖整个模型 mainLight.shadow.camera.left = -10; mainLight.shadow.camera.right = 10; mainLight.shadow.camera.top = 10; mainLight.shadow.camera.bottom = -10;
2. 降低环境光强度
你当前AmbientLight强度设为1,过亮会冲淡阴影层次,建议调整到0.3-0.5:
const ambientLight = new THREE.AmbientLight('white', 0.4);
3. 添加补光弱化阴影边缘
添加HemisphereLight模拟环境反射光,填补生硬的阴影区域:
const fillLight = new THREE.HemisphereLight('rgb(180, 200, 220)', 'rgb(80, 70, 60)', 0.3); scene.add(fillLight);
4. 配置模型阴影属性
GLTF模型默认可能未开启阴影交互,需遍历模型设置:
loader.load('https://raw.githubusercontent.com/aaadraniki/projects/web-pages/assets/models/fender_br/scene.gltf', function(gltf) { obj = gltf.scene; // 遍历所有网格,开启投射/接收阴影 obj.traverse((child) => { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; } }); scene.add(obj); });
5. 开启渲染器软阴影支持
最后给渲染器开启阴影,并设置软阴影类型:
renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 软阴影渲染模式,边缘更平滑
修改后的完整代码
const main = document.querySelector('#main'); let WIDTH = main.offsetWidth; let HEIGHT = main.offsetHeight; let scene = new THREE.Scene(); let camera = new THREE.PerspectiveCamera(15, WIDTH / HEIGHT, 0.1, 1000); camera.position.z = 5; let renderer = new THREE.WebGLRenderer(); renderer.setClearColor('rgb(99, 115, 107)'); renderer.setSize(WIDTH, HEIGHT); // 开启软阴影 renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.domElement.setAttribute("id", "Church3DObj"); main.insertBefore(renderer.domElement, main.firstChild); let controls = new THREE.OrbitControls(camera, renderer.domElement); const ambientLight = new THREE.AmbientLight('white', 0.4); const mainLight = new THREE.DirectionalLight('white', 0.6); mainLight.position.set(10, 10, 10); mainLight.castShadow = true; mainLight.shadow.mapSize.set(2048, 2048); mainLight.shadow.radius = 8; mainLight.shadow.bias = -0.0001; mainLight.shadow.camera.left = -10; mainLight.shadow.camera.right = 10; mainLight.shadow.camera.top = 10; mainLight.shadow.camera.bottom = -10; // 添加补光 const fillLight = new THREE.HemisphereLight('rgb(180, 200, 220)', 'rgb(80, 70, 60)', 0.3); scene.add(ambientLight); scene.add(mainLight); scene.add(fillLight); let loader = new THREE.GLTFLoader(); let obj = null; loader.load('https://raw.githubusercontent.com/aaadraniki/projects/web-pages/assets/models/fender_br/scene.gltf', function(gltf) { obj = gltf.scene; obj.traverse((child) => { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; } }); scene.add(obj); }); renderer.setAnimationLoop(_ => { renderer.render(scene, camera); });
调整后,灯光会呈现出柔和的明暗过渡,阴影边缘不再生硬,更接近你期望的效果。
内容的提问来源于stack exchange,提问作者aaadraniki
相关产品推荐
相关产品推荐

