欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

threeJS 创建视频纹理贴图(冰雪奇缘视频)

程序员文章站 2022-05-26 19:10:44
...

本例来源官方案例

效果图

threeJS 创建视频纹理贴图(冰雪奇缘视频)
threeJS 创建视频纹理贴图(冰雪奇缘视频)

总体步骤

① 创建场景和相机
②创建物体
③ 创建渲染器


html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        html,body{
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
                #video{
            position: fixed;
            left:0;
            bottom:0;
        }

    </style>
</head>
<body>
<div id="container">

</div>
<video id="video" loop width="400" height="300" crossOrigin="anonymous" webkit-playsinline  controls="controls" autoplay="autoplay" preload>

    <source src="./video/letitgo.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
</video>
<script type="module">


</script>
</body>
</html>


导入文件,创建全局变量和函数

    import * as THREE from "./js/three.module.js";
    import {OrbitControls} from "./js/OrbitControls.js";
    import { GUI } from './js/dat.gui.module.js';
    import Stats from './js/stats.module.js';
    import {EffectComposer} from './js/EffectComposer.js';
    import {RenderPass} from './js/RenderPass.js';
    import {ShaderPass} from './js/ShaderPass.js';
    import {CopyShader} from './js/CopyShader.js';
    import {DotScreenPass} from './js/DotScreenPass.js';
    import {FilmPass} from './js/FilmPass.js';
    import {BloomPass} from './js/BloomPass.js';
    let renderer,scene,camera,spotLight,status,cubeGeometry,material=[],materials=[],mesh,cube_count, h, counter = 1,meshes=[],composer;

    action();
    function action() {
        onload();
        run();
    }
      function onload(){

     }
     function run()
     {
     }
     function onResize()
     {
     }


①创建场景和相机

onload函数中

  let container=document.getElementById("container");//获取container

        scene=new THREE.Scene();//创建场景
        camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,10000);
        camera.position.set(0, 10, 40);//创建相机并设置位置

②创建物体

onload函数中

 let ambientLight=new THREE.AmbientLight();//添加环境光
        scene.add(ambientLight);

        spotLight=new THREE.SpotLight( 0xaabbff);//添加点光源
        spotLight.position.set(-100, 30,30);
        spotLight.intensity=1;
        scene.add(spotLight);
        //let light = new THREE.DirectionalLight( 0xaabbff, 0.3 );
        //light.position.x = 300;
        //light.position.y = 250;
        //light.position.z = - 500;
        // scene.add( light );
        let spotLightMesh=new THREE.Mesh(new THREE.SphereGeometry(1,20,20),new THREE.MeshBasicMaterial());
        spotLight.add(spotLightMesh);

        //let gridHelper=new THREE.GridHelper(30,20);
        //scene.add(gridHelper);

        let video=document.getElementById("video");
        let videoTexture=new THREE.VideoTexture(video);

        /*var texture = new THREE.VideoTexture(video);
        texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
        texture.minFilter = THREE.LinearFilter;
        var geometry = new THREE.PlaneGeometry(200, 71); //矩形平面
        var material = new THREE.MeshPhongMaterial({
            map: texture, // 设置纹理贴图
            side:THREE.DoubleSide
        }); //材质对象Material
        var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
        scene.add(mesh);*/
        cube_count = 0;
       for(let x=0;x<20;x++)
       {
           for(let y=0;y<10;y++)
           {
             cubeGeometry=new THREE.BoxBufferGeometry(1,1,1);
             let uvs=cubeGeometry.attributes.uv.array;//得到uv
             for(let i=0;i<uvs.length;i+=2)
             {//重新定义贴图位置
                 uvs[i]= ( uvs[ i ] + x ) * 1/20;
                 uvs[ i + 1 ] = ( uvs[ i + 1 ] +y ) * 1/10;
             }
             let cubeMaterial=new THREE.MeshLambertMaterial({color:0xffffff,map:videoTexture});
             mesh=new THREE.Mesh(cubeGeometry,cubeMaterial);
             mesh.position.x=(x-10)*1.1;//设置x轴排列
             mesh.position.y=y*1.1;//设置y轴排列
             mesh.position.z=0;//设置z轴排列
             mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;//设置x,y,z轴缩放
             scene.add(mesh);
             mesh.dx = 0.001 * ( 0.5 - Math.random() );//为了后期变换位置所用
             mesh.dy = 0.001 * ( 0.5 - Math.random() );
             meshes[ cube_count ] = mesh;
             cube_count += 1;
           }
       }


③创建渲染器

onload函数中

  let renderModel = new RenderPass( scene, camera );
        //let effectBloom = new BloomPass( 1.3,1,1,10 );
        //let effectFilm=new FilmPass(1,1,1,true);
        //let effectDot=new DotScreenPass();
        //effectDot.uniforms.scale.value=1;
        let effectCopy = new ShaderPass( CopyShader );

        composer = new EffectComposer( renderer );
        composer.addPass( renderModel );
        //composer.addPass( effectFilm );
        //composer.addPass( effectBloom );
        //composer.addPass( effectDot );
        composer.addPass( effectCopy );

        let guiControls=new function(){
            this.Cube=function () {

            };
            this.Equirectangular=function () {

            }
        };

        let gui=new GUI();//创建gui
        gui.add(guiControls,'Cube');
        gui.add(guiControls,'Equirectangular');

        status=new Stats();//创建频率显示
        container.appendChild(status.dom);//频率挂到左上角
        let contorl=new OrbitControls(camera,renderer.domElement);//添加鼠标滚动缩放,旋转对象

        window.addEventListener('resize',onResize,false);//浏览器大小改变监听

onResize函数中

 function onResize() {
        camera.aspect=window.innerWidth/window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth,window.innerHeight);
        composer.setSize(window.innerWidth,window.innerHeight);
    }

run函数中

function run() {
        requestAnimationFrame(run);

        if ( counter % 1000 > 200 ) {

            for ( var i = 0; i < cube_count; i ++ ) {

                mesh = meshes[ i ];

                mesh.rotation.x += 10 * mesh.dx;
                mesh.rotation.y += 10 * mesh.dy;

                mesh.position.x += 200 * mesh.dx;
                mesh.position.y += 200 * mesh.dy;
                mesh.position.z += 400 * mesh.dx;

            }

        }
        if ( counter % 1000 === 0 ) {

            for ( var i = 0; i < cube_count; i ++ ) {

                mesh = meshes[ i ];

                mesh.dx *= - 1;
                mesh.dy *= - 1;

            }

        }
        counter ++;
       renderer.render(scene,camera);
       renderer.clear();
       composer.render();
        status.update();
    }

总代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <title>Title</title>
    <style>
        html,body{
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        #video{
            position: fixed;
            left:0;
            bottom:0;
        }
    </style>
</head>
<body>
<div id="container">

</div>
<video id="video" loop width="400" height="300" crossOrigin="anonymous" webkit-playsinline  controls="controls" autoplay="autoplay" preload>

    <source src="./video/letitgo.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
</video>



<script type="module">
    import * as THREE from "./js/three.module.js";
    import {OrbitControls} from "./js/OrbitControls.js";
    import { GUI } from './js/dat.gui.module.js';
    import Stats from './js/stats.module.js';
    import {EffectComposer} from './js/EffectComposer.js';
    import {RenderPass} from './js/RenderPass.js';
    import {ShaderPass} from './js/ShaderPass.js';
    import {CopyShader} from './js/CopyShader.js';
    import {DotScreenPass} from './js/DotScreenPass.js';
    import {FilmPass} from './js/FilmPass.js';
    import {BloomPass} from './js/BloomPass.js';
    let renderer,scene,camera,spotLight,status,cubeGeometry,material=[],materials=[],mesh,cube_count, h, counter = 1,meshes=[],composer;

    action();
    function action() {
        onload();
        run();
    }
    function onload() {
        let container=document.getElementById("container");//获取container

        scene=new THREE.Scene();//创建场景
        camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,10000);
        camera.position.set(0, 10, 40);//创建相机并设置位置

        let ambientLight=new THREE.AmbientLight();//添加环境光
        scene.add(ambientLight);

        spotLight=new THREE.SpotLight( 0xaabbff);//添加点光源
        spotLight.position.set(-100, 30,30);
        spotLight.intensity=1;
        scene.add(spotLight);
        //let light = new THREE.DirectionalLight( 0xaabbff, 0.3 );
        //light.position.x = 300;
        //light.position.y = 250;
        //light.position.z = - 500;
        // scene.add( light );
        let spotLightMesh=new THREE.Mesh(new THREE.SphereGeometry(1,20,20),new THREE.MeshBasicMaterial());
        spotLight.add(spotLightMesh);

        //let gridHelper=new THREE.GridHelper(30,20);
        //scene.add(gridHelper);

        let video=document.getElementById("video");
        let videoTexture=new THREE.VideoTexture(video);

        /*var texture = new THREE.VideoTexture(video);
        texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
        texture.minFilter = THREE.LinearFilter;
        var geometry = new THREE.PlaneGeometry(200, 71); //矩形平面
        var material = new THREE.MeshPhongMaterial({
            map: texture, // 设置纹理贴图
            side:THREE.DoubleSide
        }); //材质对象Material
        var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
        scene.add(mesh);*/
        cube_count = 0;
       for(let x=0;x<20;x++)
       {
           for(let y=0;y<10;y++)
           {
             cubeGeometry=new THREE.BoxBufferGeometry(1,1,1);
             let uvs=cubeGeometry.attributes.uv.array;//得到uv
             for(let i=0;i<uvs.length;i+=2)
             {//重新定义贴图位置
                 uvs[i]= ( uvs[ i ] + x ) * 1/20;
                 uvs[ i + 1 ] = ( uvs[ i + 1 ] +y ) * 1/10;
             }
             let cubeMaterial=new THREE.MeshLambertMaterial({color:0xffffff,map:videoTexture});
             mesh=new THREE.Mesh(cubeGeometry,cubeMaterial);
             mesh.position.x=(x-10)*1.1;//设置x轴排列
             mesh.position.y=y*1.1;//设置y轴排列
             mesh.position.z=0;//设置z轴排列
             mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;//设置x,y,z轴缩放
             scene.add(mesh);
             mesh.dx = 0.001 * ( 0.5 - Math.random() );
             mesh.dy = 0.001 * ( 0.5 - Math.random() );
             meshes[ cube_count ] = mesh;
             cube_count += 1;
           }
       }


        renderer=new THREE.WebGLRenderer({antialias:true});
        renderer.setPixelRatio(window.devicePixelRatio);
        //renderer.setClearColor(0xEEEEEE);
        renderer.autoClear = false;
        renderer.gammaInput=true;
        renderer.gammaOutput=true;//inear转gamma
        renderer.setSize(window.innerWidth,window.innerHeight);
        container.appendChild(renderer.domElement);


        let renderModel = new RenderPass( scene, camera );
        //let effectBloom = new BloomPass( 1.3,1,1,10 );
        //let effectFilm=new FilmPass(1,1,1,true);
        //let effectDot=new DotScreenPass();
        //effectDot.uniforms.scale.value=1;
        let effectCopy = new ShaderPass( CopyShader );

        composer = new EffectComposer( renderer );
        composer.addPass( renderModel );
        //composer.addPass( effectFilm );
        //composer.addPass( effectBloom );
        //composer.addPass( effectDot );
        composer.addPass( effectCopy );

        let guiControls=new function(){
            this.Cube=function () {

            };
            this.Equirectangular=function () {

            }
        };

        let gui=new GUI();//创建gui
        gui.add(guiControls,'Cube');
        gui.add(guiControls,'Equirectangular');

        status=new Stats();//创建频率显示
        container.appendChild(status.dom);//频率挂到左上角
        let contorl=new OrbitControls(camera,renderer.domElement);//添加鼠标滚动缩放,旋转对象

        window.addEventListener('resize',onResize,false);//浏览器大小改变监听
    }
    function onResize() {
        camera.aspect=window.innerWidth/window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth,window.innerHeight);
        composer.setSize(window.innerWidth,window.innerHeight);
    }

    function run() {
        requestAnimationFrame(run);

        if ( counter % 1000 > 200 ) {

            for ( var i = 0; i < cube_count; i ++ ) {

                mesh = meshes[ i ];

                mesh.rotation.x += 10 * mesh.dx;
                mesh.rotation.y += 10 * mesh.dy;

                mesh.position.x += 200 * mesh.dx;
                mesh.position.y += 200 * mesh.dy;
                mesh.position.z += 400 * mesh.dx;

            }

        }
        if ( counter % 1000 === 0 ) {

            for ( var i = 0; i < cube_count; i ++ ) {

                mesh = meshes[ i ];

                mesh.dx *= - 1;
                mesh.dy *= - 1;

            }

        }
        counter ++;
       renderer.render(scene,camera);
       renderer.clear();
       composer.render();
        status.update();
    }

</script>
</body>
</html>
相关标签: threejs