Three.js r88中PointLight阴影无法渲染问题求助
解决Three.js r88中PointLight阴影不渲染的问题
我帮你排查了代码里的几个关键问题,调整后阴影就能正常显示了,具体问题和修复方案如下:
问题1:物体位置重叠导致阴影无法投射
你的平面(Plane)和球体(Sphere)默认都在场景原点(0, 0, 0),球体完全覆盖在平面上,阴影没有投射的空间。需要把平面向下移动并调整朝向,让球体处于平面上方:
// 修改平面的位置与朝向 plane.position.y = -10; plane.rotation.x = -Math.PI / 2; // 让平面水平放置
问题2:PointLight的阴影参数未正确配置
在Three.js r88版本中,PointLight开启castShadow = true后,默认的阴影贴图尺寸和相机参数不足以渲染出可见的阴影,需要手动配置:
function getLight(scene) { var light = new THREE.PointLight( 0xffffff, 1, 100 ); light.position.set( 0, 10, 0 ); light.castShadow = true; // 提升阴影贴图分辨率,避免模糊 light.shadow.mapSize.width = 1024; light.shadow.mapSize.height = 1024; // 调整阴影相机的裁剪范围,确保覆盖场景内的物体 light.shadow.camera.near = 0.1; light.shadow.camera.far = 50; scene.add( light ); var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); return light; }
问题3:球体位置优化(可选)
可以把球体向上移动一点,让阴影投射的效果更明显:
sphere.position.y = 2;
修改后的完整代码
/** * Generate a scene object with a background color **/ function getScene() { var scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); return scene; } /** * Generate the camera to be used in the scene. Camera args: * [0] field of view: identifies the portion of the scene * visible at any time (in degrees) * [1] aspect ratio: identifies the aspect ratio of the * scene in width/height * [2] near clipping plane: objects closer than the near * clipping plane are culled from the scene * [3] far clipping plane: objects farther than the far * clipping plane are culled from the scene **/ function getCamera() { var aspectRatio = window.innerWidth / window.innerHeight; var camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 1000); camera.position.set(0, 1, -30); return camera; } /** * Generate the light to be used in the scene. Light args: * [0]: Hexadecimal color of the light * [1]: Numeric value of the light's strength/intensity * [2]: The distance from the light where the intensity is 0 * @param {obj} scene: the current scene object **/ function getLight(scene) { // SHADOW var light = new THREE.PointLight( 0xffffff, 1, 100 ); light.position.set( 0, 10, 0 ); light.castShadow = true; // default false // 新增阴影配置 light.shadow.mapSize.width = 1024; light.shadow.mapSize.height = 1024; light.shadow.camera.near = 0.1; light.shadow.camera.far = 50; scene.add( light ); var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); return light; } /** * Generate the renderer to be used in the scene **/ function getRenderer() { // Create the canvas with a renderer var renderer = new THREE.WebGLRenderer({antialias: true}); // Add support for retina displays renderer.setPixelRatio(window.devicePixelRatio); // Specify the size of the canvas renderer.setSize(window.innerWidth, window.innerHeight); // SHADOW renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Add the canvas to the DOM document.body.appendChild(renderer.domElement); return renderer; } /** * Generate the controls to be used in the scene * @param {obj} camera: the three.js camera for the scene * @param {obj} renderer: the three.js renderer for the scene **/ function getControls(camera, renderer) { var controls = new THREE.TrackballControls(camera, renderer.domElement); controls.zoomSpeed = 0.4; controls.panSpeed = 0.4; return controls; } // Render loop function render() { requestAnimationFrame(render); renderer.render(scene, camera); controls.update(); }; var scene = getScene(); var camera = getCamera(); var light = getLight(scene); var renderer = getRenderer(); var controls = getControls(camera, renderer); //Create a sphere that cast shadows (but does not receive them) var sphereGeometry = new THREE.SphereBufferGeometry( 5, 32, 32 ); var sphereMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } ); var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial ); sphere.castShadow = true; //default is false sphere.receiveShadow = false; //default sphere.position.y = 2; // 新增球体位置调整 scene.add( sphere ); //Create a plane that receives shadows (but does not cast them) var planeGeometry = new THREE.PlaneGeometry( 50, 20, 32 ); var planeMaterial = new THREE.MeshPhongMaterial({ color: 0xffff00, side: THREE.DoubleSide}) var plane = new THREE.Mesh( planeGeometry, planeMaterial ); plane.receiveShadow = true; plane.position.y = -10; // 新增平面位置调整 plane.rotation.x = -Math.PI / 2; // 新增平面朝向调整 scene.add( plane ); render();
body { margin: 0; } canvas { width: 100%; height: 100% }
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js'></script> <script src='https://threejs.org/examples/js/controls/TrackballControls.js'></script>
这些修改后,你就能看到球体在黄色平面上投射的柔和阴影了。核心是确保物体之间有足够的空间让阴影投射,同时正确配置PointLight的阴影参数,让渲染器能生成清晰的阴影贴图。
内容的提问来源于stack exchange,提问作者duhaime
相关产品推荐
相关产品推荐

