You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js海浪效果创建故障:白屏转黑方块问题排查求助

问题描述

尝试用Three.js制作海浪效果,初始运行时显示白屏,调整后变为缓慢旋转的黑方块,使用的代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
        </style>
    </head>
    <body>
        
        <script src="https://cdn.jsdelivr.net/npm/three@0.143/build/three.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/three@0.143/examples/js/controls/OrbitControls.js"></script> 
        <script src="https://cdn.jsdelivr.net/npm/three@0.143/examples/js/objects/Water.js"></script>   
        <script>


            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
            camera.position.set( 0, 0, 50 );
            camera.lookAt( 0, 0, 0 );
            

            const renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

            
            const WaterGeometry = new THREE.PlaneGeometry( 45, 45 );
            const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/mK9cHLq.jpeg' );
            const material = new THREE.MeshBasicMaterial( { map: texture, side: THREE.DoubleSide } );
            const controls = new THREE.OrbitControls( camera, renderer.domElement );
            const params = {
                color: '#ffffff',
                scale: 4,
                flowX: 1,
                flowY: 1
            };


                water = new THREE.Water( WaterGeometry, material, {
                    color: params.color,
                    scale: params.scale,
                    flowDirection: new THREE.Vector2( params.flowX, params.flowY ),
                    textureWidth: 1024,
                    textureHeight: 1024
                } );



            controls.update();

            scene.add( water );

            function animate() 
            {
                requestAnimationFrame( animate );

                water.rotation.x += 0.00;
                water.rotation.y += 0.00;
                water.rotation.z += 0.01;

                renderer.render( scene, camera );
            };

            animate();
        </script>
    </body>
</html>
错误原因分析
  1. THREE.Water构造参数错误:该类仅接受几何体和配置对象两个参数,无需传入自定义MeshBasicMaterial,额外传入的材质会破坏Water内部材质的初始化流程,导致显示异常。
  2. 缺少波浪法线纹理:Water效果依赖法线纹理模拟波浪起伏与反射,未加载法线纹理时无法呈现海浪效果,只会显示纯色或黑色平面。
  3. 水面朝向错误:PlaneGeometry默认是XY平面,相机处于Z轴位置时只能看到平面边缘,需将水面旋转至XZ平面才能正常观察。
  4. 动画逻辑错误:直接旋转整个water mesh无法实现波浪流动,需更新Water内部的时间uniform变量驱动动画。
修复方案
  1. 移除自定义material参数,正确调用THREE.Water构造函数。
  2. 加载Water所需的法线纹理(可使用Three.js官方示例纹理或自行准备)。
  3. 将水面旋转至XZ平面(设置water.rotation.x = -Math.PI / 2)。
  4. 在动画循环中更新Water的时间参数,实现波浪流动效果。
  5. 添加窗口大小监听,确保渲染器与相机比例随窗口变化同步更新。
修正后的代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Three.js Water Effect</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script src="https://cdn.jsdelivr.net/npm/three@0.143/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.143/examples/js/controls/OrbitControls.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.143/examples/js/objects/Water.js"></script>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, 10, 30);
        camera.lookAt(0, 0, 0);

        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // 创建水面几何体
        const waterGeometry = new THREE.PlaneGeometry(100, 100);

        // 加载水面法线纹理,替换为你自己的纹理路径(可使用Three.js官方示例纹理)
        const textureLoader = new THREE.TextureLoader();
        const waterNormals = textureLoader.load('path/to/your/water-normal-texture.jpg');
        waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;

        // 初始化Water
        const params = {
            color: '#001e0f',
            scale: 4,
            flowDirection: new THREE.Vector2(1, 1),
            textureWidth: 1024,
            textureHeight: 1024
        };

        const water = new THREE.Water(waterGeometry, {
            color: params.color,
            scale: params.scale,
            flowDirection: params.flowDirection,
            textureWidth: params.textureWidth,
            textureHeight: params.textureHeight,
            normalMap0: waterNormals,
            normalMap1: waterNormals
        });

        // 调整水面朝向到XZ平面
        water.rotation.x = -Math.PI / 2;

        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;

        scene.add(water);

        // 窗口大小变化适配
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        function animate(time) {
            requestAnimationFrame(animate);

            // 更新Water时间参数,驱动波浪流动动画
            water.material.uniforms['time'].value += 1.0 / 60.0;

            controls.update();
            renderer.render(scene, camera);
        }

        animate();
    </script>
</body>
</html>
关键修复点说明
  • Water构造调用:移除多余的material参数,改为传入包含法线纹理的配置对象,确保Water内部材质正确初始化。
  • 法线纹理设置:加载法线纹理并设置重复映射,为波浪效果提供必要的视觉数据。
  • 水面朝向调整:旋转水面至XZ平面,让相机可以正常观察完整水面。
  • 动画逻辑修正:通过更新时间uniform变量驱动波浪流动,替代旋转整个mesh的错误方式。
  • 窗口适配:添加resize事件监听,保证窗口变化时渲染器和相机参数同步更新。

内容的提问来源于stack exchange,提问作者Cambria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:18:20