three.js学习(长期)

发布于 2024-01-08  208 次阅读


three.js

创建一个相机

//创建场景
const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
  75, //视角
  window.innerWidth / window.innerHeight, //宽高比
  0.1, //相机近屏面
  1000 //相机远屏面
);
//创建一个画布
const renderer = new THREE.WebGLRenderer();
//添加一个控制器
const controls = new OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;//添加摄像头拖动阻尼
controls.dampingFactor = 0.05;//添加摄像头拖动阻尼

// controls.autoRotate = true;//自动旋转
// controls.autoRotateSpeed = 40;//旋转速度
renderer.setSize(window.innerWidth, window.innerHeight);
let container:any = '';
//创建一种材质
  const material = new THREE.MeshBasicMaterial({ color: 'pink' });
//创建一个正方体
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  //创建一个网格,让立方体在场景中可以显现出来
const cube = const cube = new THREE.Mesh( geometry, material );
//往场景中加入这个正方体
scene.add(cube);
cube.position.set(x,y,z)

//缩放
cube.scale.set(x,y,z);

//旋转,制定一个轴,按照这个轴来旋转这个物体
//const a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );

/

监听方法

监听屏幕大小拖动

  window.addEventListener("resize",()=>{
    renderer.setSize(window.innerWidth, window.innerHeight);
  });

全屏方法

renderer.domElement.requestFullscreen();

创建一个GUI,方便快速调试

import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
const gui = new GUI();
  let guiObj = {
    full:fullFn  };
   //第一个传入一个对象,第二个传入对象键值对名称,会自动判断这个是不是方法,后面用.name("")可以修改按钮名称
  gui.add(guiObj,"full").name("全屏") ;

创建一个材质对象

//导入纹理f翻译器
const textureLoader = new THREE.TextureLoader();
 const cubeGeometry1 = new THREE.BoxGeometry(1,1,1);
 //圆
 const cubeGeometry2 = new THREE.SphereGeometry(1, 32, 16);

// 返回一个门的对象
const USA = textureLoader.load('./assets/amereca.png');
const amereca = textureLoader.load('./assets/USA.png');
//纹理偏移设置0-1
amereca.offset.set(0.5,0.5);
amereca.offset.x(0.5,0.5);
//设置纹理的中心
amereca.center.set(0.2,0.5);

//纹理旋转45度
amereca.rotation = Math.PI/4;

const cube1 = new THREE.Mesh(cubeGeometry1,material1);
const cube2 = new THREE.Mesh(cubeGeometry2,material2);
cube2.position.x = 2;
scene.add(cube1);
scene.add(cube2);
renderer.render(scene, camera);

图案纹理

//导入纹理f翻译器
const textureLoader = new THREE.TextureLoader();
const USA = textureLoader.load('./assets/wenli1.png');

设置环境遮挡

const material1 = new THREE.MeshStandardMaterial({
        color: "transparent",
        map: door,
        //黑白透明贴图
        alphaMap:doorAplha,
        // 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
        aoMapIntensity: 2,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        //环境遮挡地图
        aoMap:doorAo,
    })

    const material2 = new THREE.
    MeshStandardMaterial({
        color: "transparent",
        map: door,
        alphaMap:doorAplha,
        // 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        //环境遮挡地图
    })
    //需要第二组UV,第二组纹理贴图

// 对比
    cube1 = new THREE.Mesh(planeGeometry, material1);
    cube2 = new THREE.Mesh(cubeGeometry1, material2);
    //设置第二组vu
    planeGeometry.setAttribute('uv2',new THREE.BufferAttribute(planeGeometry.attributes.uv.array,2));

材质和光

创建一个标准材质,必须有光,没光的话显示未黑色
const material1 = new THREE.MeshStandardMaterial({
  // color:"transparent",
  color:"#ffff00",
  map:USA,
  // 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
  aoMapIntensity:1,
  transparent:true, 
  opacity:0.9
})

// 基础材质
const material2 = new THREE.MeshBasicMaterial({
  // color:"transparent",
  color:"transparent",
  map:amereca,
  side: THREE.DoubleSide
});

//添加环境光,四面八方打过来的光AmbientLight el1颜色。el2强度0.5——1
  const light = new THREE.AmbientLight( 0x404040,1 ); // 柔和的白光
  scene.add(light);

//平行光DirectionalLight太阳光
  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
//有点抽象,相当于设置太阳的位置
  directionalLight.position.y = 10;
  directionalLight.position.x = 10;
  scene.add(directionalLight);

置换贴图

    const door = textureLoader.load("./assets/door.png")
    const doorAplha = textureLoader.load("./assets/doorwblack.png")
    const doorAo = textureLoader.load("./assets/doornocolor.png")
    const doorColor = textureLoader.load("./assets/doorcolor.png")
    // 导入置换贴图
    const doorHeight = textureLoader.load("./assets/doorbgray.png")

  //创建一个平面。第三个参数和第四个参数分别是
 // widthSegments — (可选)平面的宽度分段数,默认值是 1。
//heightSegments — (可选)平面的高度分段数,默认值是 1。
    const planeGeometry = new THREE.PlaneBufferGeometry(1, 1,200,200);

粗糙度设置、金属度设置

    const directionalLight = new THREE.DirectionalLight( 0xcccccc, 1 );
    directionalLight.position.set(0,0,10);
    scene.add(directionalLight);
设置一个平行于z轴的太阳光

    const material1 = new THREE.MeshStandardMaterial({
        color: "transparent",
        map: door,
        alphaMap: doorAplha,
        // 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
        aoMapIntensity: 2,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        //环境遮挡地图
        aoMap: doorAo,
        displacementMap:doorHeight,
        //突出影响程度
        displacementScale:0.2,
            //粗糙度
        roughness:1,
        //粗糙度的纹理
        roughnessMap:doorRoughness,
                //金属度
        metalness:0,
        //金属贴图
        metalnessMap:doorColor,
        //渲染为线
        wireframe:ture
    });

法线贴图

颜色代表向量。根据光和颜色计算光的折射

    const material1 = new THREE.MeshStandardMaterial({
        color: "transparent",
        map: door,
        alphaMap: doorAplha,
        // 环境遮挡效果的强度。默认值为1。零是不遮挡效果。
        aoMapIntensity: 2,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        //环境遮挡地图
        aoMap: doorAo,
        displacementMap:doorHeight,
        //突出影响程度
        displacementScale:0.2,
            //粗糙度
        roughness:1,
        //粗糙度的纹理
        roughnessMap:doorRoughness,
        //金属度
        metalness:1,
        //金属贴图
        metalnessMap:doorColor,
        //法线贴图
        normalMap:doorNormal
    });

环境纹理贴图

cubeTextureLoader

贴图一键生成地址

https://jaxry.github.io/panorama-to-cubemap/

https://www.360toolkit.co/convert-spherical-equirectangular-tocubemap.html

let cubeTextureLoader = new THREE.CubeTextureLoader();

x正,x反。Y正Y反,z正z反
let envMapTexture = cubeTextureLoader.setPath('./assets/sky/').load([
  'px.jpg',
  'nx.jpg',
  'py.jpg',
  'ny.jpg',
  'pz.jpg',
  'nz.jpg',
]);
    //给场景添加环境贴图
  scene.background = envMapTexture;
    //给所有的物体添加默认的环境贴图
    scene.environment = envMapTexture

贴图纹理下载收藏网站

POLIIGON
3dtextures.me
arroway-textures.ch
Quixie bridge//需注册虚幻5引擎账号

LoadingManager加载进度监视器

设置单张纹
textureLoader.load ( url : String, onLoad : Function, onProgress : Function, onError : Function ) : Texture
//四个参数分别是路径,加载完成方法,加载进度方法,加载失败方法

//多张纹理图添加纹理监视管理器
let event = {
        onLoad : function(e){
            console.log("加载完成"+e);
        },
        onProgress : function(url,num,total){
            console.log("加载地址"+url);
            console.log("加载数量"+num);
            console.log("加载总数"+total);
            console.log("加载百分比"+((num/total)*100).toFixed(2));

        },
        onError:function(e){
            console.log("加载失败"+e);

        }
    }

    // 设置加载管理器
    const loadingManager = new THREE.LoadingManager(event.onLoad,event.onProgress,event.onError);

const textureLoader = new THREE.TextureLoader(loadingManager);

HDR经纬线映射

hdr图片下载
https://zhuanlan.zhihu.com/p/659861294?utm_id=0
https://unsplash.com/s/photos/hdr

灯光与阴影

开启阴影贴图
renderer.render(scene, camera);
//开启灯光阴影
 dirLight.castShadow = true;
 //设置投影模糊度
 dirLight.shadow.radius = 10;
//分辨率、大小默认512*512
 dirLight.shadow.mapSize.set(1024,1024);

//投射阴影面
spCube.castShadow = true;
//接收阴影面
cubePlane.receiveShadow = true;

不同浏览器全屏方案

/* 获取(<video>)元素 */
var elem = document.getElementsByTagName("video")[0];

/* 全屏查看 */
function openFullscreen() {
  if (elem.requestFullscreen) {
     elem.requestFullscreen();
  } else if (elem.mozRequestFullScreen) {/* Firefox */
     elem.mozRequestFullScreen();
  } else if (elem.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
     elem.webkitRequestFullscreen();
  } else if (elem.msRequestFullscreen) { /* IE/Edge */
     elem.msRequestFullscreen();
  }
}

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。