threeJS 双场景双相机创建立方体环境贴图和全景贴图

本例来源于官方案例

效果图

立方体贴图

全景贴图

总体步骤

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

html代码




    
    Title
    


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

   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';
  
 let renderer,scene,camera,spotLight,status,cameraCube,sceneCube,cubeMesh,SphereMaterial;

    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, 0, 1000);//创建相机并设置位置


        sceneCube = new THREE.Scene();//创建立方体场景(副)
        cameraCube=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,10000);

②创建物体

onload函数中

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

        spotLight=new THREE.SpotLight(0xffffff);//添加点光源
        spotLight.position.set(-600, 300,300);
        spotLight.intensity=3;
        scene.add(spotLight);
        let spotLightMesh=new THREE.Mesh(new THREE.SphereGeometry(15,20,20),new THREE.MeshBasicMaterial());
        spotLight.add(spotLightMesh);

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

        //立方体贴图
        let textureCube=new THREE.CubeTextureLoader().setPath("img/").load(["posx.jpg", "negx.jpg","posy.jpg","negy.jpg","posz.jpg","negz.jpg"]);
        textureCube.encoding=THREE.sRGBEncoding;//在导入材质时,会默认将贴图编码格式定义为Three.LinearEncoding,故需将带颜色信息的贴图(baseColorTexture, emissiveTexture, 和 specularGlossinessTexture)手动指定为Three.sRGBEncoding
        textureCube.mapping=THREE.CubeReflectionMapping;//立方体反映射①
        textureCube.format=THREE.RGBFormat;//默认THREE.RGBAFormat,对于JPG会自动设置为THREE.RGBFormat ②
       // console.log(textureCube);

        let SphereGeometry=new THREE.SphereBufferGeometry(300.0, 48, 24);
            SphereMaterial=new THREE.MeshLambertMaterial({envMap:textureCube});
        let SphereMesh=new THREE.Mesh(SphereGeometry,SphereMaterial);
        scene.add(SphereMesh);

        let cubeShader=THREE.ShaderLib["cube"];
        console.log(THREE.ShaderLib);
        let cubeMaterial=new THREE.ShaderMaterial({
               fragmentShader:cubeShader.fragmentShader,
               vertexShader:cubeShader.vertexShader,
               uniforms:cubeShader.uniforms,
               depthWrite:false,
               side: THREE.BackSide
        });
        cubeMaterial.uniforms["tCube"].value=textureCube;
        console.log(cubeMaterial);

        //全景贴图
        let panorama=new THREE.TextureLoader().load("./img/2294472375_24a3b8ef46_o.jpg");
        panorama.mapping = THREE.EquirectangularReflectionMapping;
        panorama.magFilter = THREE.LinearFilter;//③
        panorama.minFilter = THREE.LinearMipmapLinearFilter;//④
        panorama.encoding = THREE.sRGBEncoding;
        let panoramaShader=THREE.ShaderLib["equirect"];
        let panoramaMaterial=new THREE.ShaderMaterial({
            fragmentShader:panoramaShader.fragmentShader,
            vertexShader: panoramaShader.vertexShader,
            uniforms:panoramaShader.uniforms,
            depthWrite: false,
            side: THREE.BackSide
        });
        panoramaMaterial.uniforms["tEquirect"].value=panorama;


        cubeMesh=new THREE.Mesh(new THREE.BoxBufferGeometry( 10, 100, 100 ),cubeMaterial);
        sceneCube.add(cubeMesh);

解释

 ①:textureCube.mapping:就是UV贴图的类型,它的取值如下
 THREE.CubeReflectionMapping:立方体反射映射
 THREE.CubeRefractionMapping:立方体折射映射
 THREE.EquirectangularReflectionMapping:圆柱反射映射
 THREE.EquirectangularRefractionMapping:圆柱折射映射
 THREE.SphericalReflectionMapping:球面反t射映射
 ② :textureCube.format
 缺省纹理格式为THREE.RGBAFormat。其他格式有:
THREE.AlphaFormat:对应于GL_ALPHA。Alpha 值
THREE.RGBFormat:Red, Green, Blue 三原色值
THREE.RGBAFormat:Red, Green, Blue 和 Alpha 值
THREE.LuminanceFormat:灰度值
THREE.LuminanceAlphaFormat:灰度值和 Alpha 值
THREE.RGBEFormat

③ panorama.magFilter
该属性定义当一个纹理单元(texel)覆盖多个像素点时纹理如何采样。缺省为 THREE.LinearFilter,表示获取4个最近的纹理单元执行双向线性插值计算(显示效果好)。另外的选项是 THREE.NearestFilter, 表示使用最近的texel(性能优)

④:panorama.minFilter
该属性定义当一个纹理单元(texel)不足以覆盖单个像素点时纹理如何采样。缺省为 THREE.LinearMipMapLinearFilter, 表示使用多级纹理贴图(mipmapping)以及一个三线性滤波器。
其他选项是:
THREE.NearestFilter:最近滤镜。在纹理基层上执行最邻近过滤。
THREE.NearestMipMapNearestFilter:选择最临近的mip层,并执行最临近的过滤。
THREE.NearestMipMapLinearFilter:在mip层之间执行线性插补,并执行最临近的过滤。
THREE.LinearFilter:在纹理基层上执行线性过滤。
THREE.LinearMipMapNearestFilter:选择最临近的mip层,并执行线性过滤。
THREE.LinearMipMapLinearFilter:在mip层之间执行线性插补,并执行线性过滤。

参考博客 Three.js Texture纹理属性详解

THREE.ShaderMaterial 参考博客Three.js高级材质THREE.ShaderMaterial

③创建渲染器

onload函数中

    renderer=new THREE.WebGLRenderer({antialias:true});
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.autoClear=false;
        renderer.gammaInput=true;
        renderer.gammaOutput=true;//inear转gamma
        renderer.setSize(window.innerWidth,window.innerHeight);
        container.appendChild(renderer.domElement);
         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();

        cameraCube.aspect = window.innerWidth / window.innerHeight;
        cameraCube.updateProjectionMatrix();
        renderer.setSize(window.innerWidth,window.innerHeight);
    }

run函数中

function run() {
        requestAnimationFrame(run);
        camera.lookAt(scene.position);
        cameraCube.rotation.copy(camera.rotation);//赋值相机的位置
        renderer.render(sceneCube,cameraCube);
        renderer.render(scene,camera);
        status.update();

    }

④创建GUI

onload函数中

  let guiControls=new function(){
            this.Cube=function () {
                cubeMesh.material = cubeMaterial;
                cubeMesh.visible = true;
                SphereMaterial.envMap = textureCube;
                SphereMaterial.needsUpdate = true;
            };
           this.Equirectangular=function () {
                cubeMesh.material = panoramaMaterial;
                cubeMesh.visible = true;
                SphereMaterial.envMap=panorama;
                SphereMaterial.needsUpdate = true;
            }
        };

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

总代码




    
    Title
    


你可能感兴趣的:(threejs)