three.js用THREE.CubeCamera和环境贴图创建反光效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37338983/article/details/82659082

在文章:three.js贴图之CubeTextureLoader全景贴图中已经讲过全景贴图的应用,本文将进一步扩展全景贴图的功能,结合THREE.CubeCamera功能,创建出一个具有反光效果的场景,首先来看看看看THREE.CubeCamera的用法:

let cubeCamera = new THREE.CubeCamera(0.1, 10000, 128);//实例化一个cubeCamera
scene.add(cubeCamera);//将其添加到场景中
let dynamicEnvMaterial = new THREE.MeshBasicMaterial({
    envMap: cubeCamera.renderTarget, side: THREE.DoubleSide
}); //新建一个动态环境材料,envMap为环境贴图,设置为cubeCamera的渲染目标
cubeCamera.updateCubeMap(renderer, scene);//更新渲染立方体贴图

THREE.CubeCamera(near, far, cubeResolution)总共接收三个参数,前两个参数表示最近距离和最远距离,和THREE.PerspectiveCamera中的near和far一个道理,最后一个参数按字面理解为立方体分辨率,通俗的理解为物体对场景反光的清晰度,即越大越清晰,可以取128、256、512、1080等;本文实现一个球将周围场景反光,类似于镜子,你可以在球的表面上看到周围场景的镜像。demo实现效果如下图:

demo代码如下: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>场景反光</title>
    <script type="text/javascript" src="build/three.js"></script>
    <script type="text/javascript" src="js/controls/OrbitControls.js"></script>
    <script type="text/javascript" src="js/libs/stats.js"></script>
    <style>
        body {
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>
<script type="text/javascript" >
    let container1 = document.createElement('div');
    document.body.appendChild(container1);

    let container2 = document.createElement('div');
    document.body.appendChild(container2);

    let scene = undefined;
    let renderer = undefined;
    let camera = undefined;
    let cubeCamera = undefined;
    let pointLight = ambientLight = undefined;
    let sphere  = undefined, cube = undefined;
    let controls = undefined;
    let stats = undefined;

    main();
    render();

    function main() {
        initScene();
        initRenderer(container1);
        initCamera();
        initLight();
        initControls();
        createScene();
        initStats(container2);
        window.addEventListener('resize', onWindowResize, false);
    }

    function initScene() {
        scene = new THREE.Scene();
    }

    function initCamera() {
        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, 5, 35);
        camera.lookAt(scene.position);
    }

    function initRenderer(container1) {
        renderer = new THREE.WebGLRenderer({antialias:true});
        renderer.setClearColor(0xffffff, 1.0);
        renderer.setSize(window.innerWidth, window.innerHeight);
        container1.appendChild(renderer.domElement);
    }

    function initLight() {
        ambientLight = new THREE.AmbientLight(0xffffff, 0.35);
        scene.add(ambientLight);

        pointLight = new THREE.PointLight(0xffffff);
        pointLight.position.set(10, 10, 10);
        scene.add(pointLight);
    }

    function initControls() {
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.autoRotate = false;
        controls.enableKeys = true;
    }

    function textureBox() {
        let geometry = new THREE.BoxGeometry(3, 3, 3, 30, 30, 30);
        let map = new THREE.TextureLoader().load('textures/brick_bump.jpg');
        let material = new THREE.MeshPhongMaterial({map:map, side: THREE.DoubleSide});
        let box = new THREE.Mesh(geometry, material);

        scene.add(box);
    }

    function createScene() {

        //创建一个立方体贴图
        let textureCube = new THREE.CubeTextureLoader().setPath("textures/cube/Park3Med/")
            .load([
                'px.jpg',
                'nx.jpg',
                'py.jpg',
                'ny.jpg',
                'pz.jpg',
                'nz.jpg'
            ]);
        textureCube.format = THREE.RGBFormat;
        textureCube.mapping = THREE.CubeReflectionMapping;
        //创建用户shader
        let shader = THREE.ShaderLib["cube"];
        shader.uniforms["tCube"].value = textureCube;


        let material = new THREE.ShaderMaterial({
            fragmentShader: shader.fragmentShader,
            vertexShader: shader.vertexShader,
            uniforms: shader.uniforms,
            side: THREE.DoubleSide
        });

        let skyBox = new THREE.Mesh(new THREE.BoxGeometry(800, 800, 800), material);
        scene.add(skyBox);

        cubeCamera = new THREE.CubeCamera(0.1, 10000, 1080);
        scene.add(cubeCamera);

        let sphereGeo = new THREE.SphereGeometry(10, 30, 30);
        let cubeGeo = new THREE.BoxGeometry(10, 10, 10, 10, 10, 10);

        let dynamicEnvMaterial = new THREE.MeshBasicMaterial({
            envMap: cubeCamera.renderTarget, side: THREE.DoubleSide
        });
        let envMaterial = new THREE.MeshBasicMaterial({
            envMap: textureCube, side:THREE.DoubleSide
        });

        sphere = new THREE.Mesh(sphereGeo, dynamicEnvMaterial);
        scene.add(sphere);

        cube = new THREE.Mesh(cubeGeo, envMaterial);
        cube.position.set(30, 0, 0);
        scene.add(cube);

    }


    function initStats(container2) {
        stats = new Stats();
        stats.setMode(0);

        stats.domElement.style.position = 'absolute';
        stats.domElement.style.left = '0px';
        stats.domElement.style.top = '0px';

        container2.appendChild(stats.domElement);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight);
    }

    function render() {
        controls.update();
        stats.update();
        // sphere.visible = false;
        cubeCamera.updateCubeMap(renderer, scene);
        // sphere.visible = true;

        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }

</script>


</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_37338983/article/details/82659082