Three.js如何实现逼真的光照(阳光)?

28

我正尝试使用Three.js创建一个小的第一人称游戏,但是我在处理光照方面遇到了问题。基本上,我想模拟太阳并使其绕着轴旋转,并投射光线。目前我正在使用THREE.DirectionalLight,但它只朝一个方向照亮,因此立方体的侧面仍然是黑色/暗色。

我需要使用多个灯光使所有物体都能被照亮吗?或者我能否通过地面/物体反射光线?

3个回答

24

是的,您需要使用多个灯光来实现这一点,模拟反射光。计算真实的反射光没有内置功能(并且计算复杂/昂贵)。您有各种选择。

第二个定向光源可以始终处于与太阳相反的位置和方向。

一个常量半球光。半球照明会得到天空颜色、地面颜色和强度,并为您的照明增加一些不错的额外深度。

//                                    sky color ground color intensity 
hemiLight = new THREE.HemisphereLight( 0x0000ff, 0x00ff00, 0.6 ); 

这里有一个可用的示例:https://threejs.org/examples/#webgl_lights_hemisphere

您可以使用任何组合的不同灯光,但要注意存在性能折衷。

还值得一提的是半Lambert着色,它可以通过在材质中将wrapAround属性设置为true来启用。这会使黑色渐变更加柔和,从而减少强烈光照产生的影响,使色调更加平稳,黑色更少。


1
谢谢!将wrapAround设置为true已经解决了问题。现在没有黑色,即使不直接在光线下,颜色仍然可见,这正是我想要的。我已经更新了原始链接 :) 现在只需要弄清楚如何解决我的阴影问题。 - Joey Morani
4
自此评论发布以来,似乎已经删除了wrapAround选项。现在该如何实现这种效果? - Toivo Säwén

22

我使用这两种灯光的组合来制作这个视频:http://www.youtube.com/watch?v=m68FDmU0wGw

            var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.6 );
            hemiLight.color.setHSV( 0.6, 0.75, 0.5 );
            hemiLight.groundColor.setHSV( 0.095, 0.5, 0.5 );
            hemiLight.position.set( 0, 500, 0 );
            scene.add( hemiLight );

            var dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
            dirLight.position.set( -1, 0.75, 1 );
            dirLight.position.multiplyScalar( 50);
            dirLight.name = "dirlight";
            // dirLight.shadowCameraVisible = true;

            scene.add( dirLight );

            dirLight.castShadow = true;
            dirLight.shadowMapWidth = dirLight.shadowMapHeight = 1024*2;

            var d = 300;

            dirLight.shadowCameraLeft = -d;
            dirLight.shadowCameraRight = d;
            dirLight.shadowCameraTop = d;
            dirLight.shadowCameraBottom = -d;

            dirLight.shadowCameraFar = 3500;
            dirLight.shadowBias = -0.0001;
            dirLight.shadowDarkness = 0.35;

1
这太棒了。源代码在哪里可以找到? - chopper
1
很遗憾,还没有。我本打算打开它的,只是没找到时间。如果需要的话,我可以找出来。 - dirkk0

1
您可以使用scene.environment来完成此任务,这里已经有一个很好的例子:https://gltf-viewer.donmccurdy.com/。请查看gltf-viewer的代码,它在阳光方面做得非常出色:https://github.com/donmccurdy/three-gltf-viewer/blob/main/src/viewer.js。请注意environments变量,它们使用venice_sunset_1k.hdr作为默认背景。更详细地说,它们使用背景作为环境,但没有“显示”它们,您可以使用以下代码:
    this.pmremGenerator = new PMREMGenerator( this.renderer );
    this.pmremGenerator.compileEquirectangularShader();
    var rgbe_loader = new RGBELoader();
    var that = this;
    rgbe_loader.setDataType(UnsignedByteType).load("/environment/venice_sunset_2k.hdr", function(texture) {

        var envMap = that.pmremGenerator.fromEquirectangular(texture).texture;

        that.scene.environment = envMap;

        texture.dispose();
        that.pmremGenerator.dispose();

    });

hdr文件可以在https://polyhaven.com/a/venice_sunset找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接