THREE.js

Three.js

一.Demo 渲染一个cube

渲染 四部曲:

  1. 场景
  2. 相机
  3. 物体
  4. 渲染

1.场景

const scence = new THREE.Scene();

2.相机

new THREE.PerspectiveCamera(fov,aspect ,near,far)
@zh
@param fov — 相机最大视角
@paramaspect — 相机宽高比
@param aspect — 相机最近渲染距离
@param far — 相机最远渲染距离

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
scence.add(camera);

3.物体

  1. 骨架
    new THREE.BoxGeometry(width , height , depth );
    @param width — — Width of the sides on the X axis.
    @param height— — Height of the sides on the Y axis.
    @param depth — — Depth of the sides on the Z axis.
  2. 材质
    new THREE.MeshBasicMaterial()
    参数很多 详见添加链接描述
  3. 物体
    new THREE.Mesh(geometry,material)
    @param geometry 物体骨架
    @param material 物体
const cubeGaomerty = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xf7ff4b });
const cube = new THREE.Mesh(cubeGaomerty,cubeMaterial);
scence.add(cube);

4.渲染

  1. 创建渲染器
  2. 设置渲染范围
  3. 将渲染节点添加到dom节点
  4. 渲染场景和相机
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scence,camera);
function render() { //跟随浏览器渲染
  renderer.render(scence,camera);
  window.requestAnimationFrame(render);
}
render();

二.轨道控制器与坐标轴

控制器
new OrbitControls (object,domElement)
@param object 控制的相机或物体
@praram domElement 渲染节点
坐标轴
new THREE.AxesHelper(num)
@param num 长度

//控制器
const control = new OrbitControls(camera,renderer.domElement);

//坐标轴
const axesHelper = new THREE.AxesHelper(5);
scence.add(axesHelper);

三.移动物体

  1. 直接修改物体位置
cube.positiom.set();

2.修改x,y,z

cube.postion.x = 1;

四.缩放物体scale

verctor3

cube.scale.set(1,2,3);
cube.scale.x = 2;

五.旋转物体rotaion

verctor3
cube.rotaion.set(Eolr());

cube.rotaion.set(Math.PI/4,0,0);

六.requestAnimationFrame

默认传入参数 nowTime 运行时长

function render(nowTime) {
  let time = (nowTime / 1000) % 5;
  cube.position.x = time * 1
  // console.log(time);
  cube.rotation.x = time * (Math.PI / 30);

  renderer.render(scence, camera);
  window.requestAnimationFrame(render);//请求动画帧
}

数值限制小技巧 你要限制 nowTime 到 x 可以这样处理 let time = (nowTime / 1000) % x 这样 time 到 x 就变成了0;

七.clock 跟踪时间

new THREE.Clock() ;

构造函数

Clock( autoStart : Boolean )
autoStart — (可选) 是否要在第一次调用 .getDelta() 时自动开启时钟。默认值是 true。

属性

.autoStart : Boolean
如果设置为 true,则在第一次调用 .getDelta() 时开启时钟。默认值是 true。

.startTime : Float
存储时钟最后一次调用 start 方法的时间。默认值是 0。

.oldTime : Float
存储时钟最后一次调用 start, .getElapsedTime() 或 .getDelta() 方法的时间。默认值是 0。

.elapsedTime : Float
保存时钟运行的总时长。默认值是 0。

.running : Boolean
判断时钟是否在运行。默认值是 false。

方法

.start () : undefined
启动时钟。同时将 startTime 和 oldTime 设置为当前时间。 设置 elapsedTime 为 0,并且设置 running 为 true.

.stop () : undefined
停止时钟。同时将 oldTime 设置为当前时间。

.getElapsedTime () : Float
获取自时钟启动后的秒数,同时将 .oldTime 设置为当前时间。
如果 .autoStart 设置为 true 且时钟并未运行,则该方法同时启动时钟。

.getDelta () : Float
获取自 .oldTime 设置后到当前的秒数。 同时将 .oldTime 设置为当前时间。
如果 .autoStart 设置为 true 且时钟并未运行,则该方法同时启动时钟。

八.GSAP 动画库

npm i gsap
gsap.to() : tween参数过多 详见: https://greensock.com/docs/v3/GSAP/gsap.to()
例:

// target the element with a class of "green" - rotate and move TO 100px to the left over the course of 1 second. 
gsap.to(".green", {
	rotation: 360, 
	x: 100, 
	duration: 1  ,
	onComplete: () => { console.log("动画结束"); },
	onStart: () => { console.log("动画开始")};
	}
);
//监听双击事件
window.addEventListener("dblclick", () => {
  // animation.isActive() ? animation.pause() : animation.resume();
  //全屏事件
  let fullScreenElement = document.fullscreenElement;
  if (!fullScreenElement) {
    renderer.domElement.requestFullscreen();
  } else {
    document.exitFullscreen()
  }
})

九.dat.gui 库快速调节参数

npm i dat.gui

//dat.gui
const gui = new dat.GUI();
gui.add(cube.position, "x").min(0).max(5).step(0.01)
  .onChange((value) => { console.log("修改了position" + value); })
  .onFinishChange((value) => { console.log("修改完 position" + value); })
  .name("cube.position.x");


const params = {
  color: "#ffff00",
  fn: () => {
    gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 })
  }
}
gui.addColor(params, "color").onChange((value) => {
  cube.material.color.set(value);
})
gui.add(params, "fn").name("立方体运动");

let folder = gui.addFolder("设置立方体");
folder.add(cube, "visible").name("显示");
folder.add(cube.material, "wireframe");

十.几何体

const cubeGeomerty = new THREE.BoxGeometry(1, 1, 1);
console.log(cubeGeomerty);

1.几何体之 .attributes

.attributes : Object
通过 hashmap 存储该几何体相关的属性,hashmap 的 id 是当前 attribute 的名称,值是相应的 buffer。 你可以通过 .setAttribute 和 .getAttribute 添加和访问与当前几何体有关的 attribute。

attributes.position : 以数组记录位置
attributes.normal : 以数组记录法线
attributes.uv : 平面的二维展开图
例子:

const geometry = new THREE.BufferGeometry();
// create a simple square shape. We duplicate the top left and bottom right
// vertices because each vertex needs to appear once per triangle.
//三个为一组 x,y,z ,左手坐标系
const vertices = new Float32Array( [
	-1.0, -1.0,  1.0,
	 1.0, -1.0,  1.0,
	 1.0,  1.0,  1.0,

	 1.0,  1.0,  1.0,
	-1.0,  1.0,  1.0,
	-1.0, -1.0,  1.0
] );

// itemSize = 3 because there are 3 values (components) per vertex
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
const mesh = new THREE.Mesh( geometry, material );

2.官方的几何体

见文档: 官方的几何体

十二.纹理

例子


//纹理
const textureLoad = new THREE.TextureLoader();
const texture = textureLoad.load("./texture/door/color.jpg")

//物体  
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ map: texture });
const mesh = new THREE.Mesh(geometry, material);
scence.add(mesh)

1.纹理偏移

纹理

属性

.rotation : number
纹理将围绕中心点旋转多少度,单位为弧度(rad)。正值为逆时针方向旋转,默认值为0。

.center : Vector2
旋转中心点。(0.5, 0.5)对应纹理的正中心。默认值为(0,0),即左下角。

.wrapS : number
这个值定义了纹理贴图在水平方向上将如何包裹,在UV映射中对应于U。
默认值是THREE.ClampToEdgeWrapping,即纹理边缘将被推到外部边缘的纹素。 其它的两个选项分别是THREE.RepeatWrapping和THREE.MirroredRepeatWrapping。 请参阅texture constants来了解详细信息。

.wrapT : number
这个值定义了纹理贴图在垂直方向上将如何包裹,在UV映射中对应于V。
可以使用与 .wrapS : number相同的选项。

.magFilter : number
当一个纹素覆盖大于一个像素时,贴图将如何采样。默认值为THREE.LinearFilter, 它将获取四个最接近的纹素,并在他们之间进行双线性插值。 另一个选项是THREE.NearestFilter,它将使用最接近的纹素的值。
请参阅texture constants页面来了解详细信息。

.minFilter : number
当一个纹素覆盖小于一个像素时,贴图将如何采样。默认值为THREE.LinearMipmapLinearFilter, 它将使用mipmapping以及三次线性滤镜。

十三.基础网格材质

.alphaMap : Texture
alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。

仅使用纹理的颜色,忽略alpha通道(如果存在)。 对于RGB和RGBA纹理,WebGL渲染器在采样此纹理时将使用绿色通道, 因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。 Luminance-only以及luminance/alpha纹理也仍然有效。

.map : Texture
颜色贴图。可以选择包括一个alpha通道,通常与.transparent 或.alphaTest。默认为null。

.aoMap : Texture
该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。

十四.标准网格材质

位移贴图

.displacementMap : Texture
位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象, 以及充当真实的几何体。位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。

.displacementScale : Float
位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。\

粗糙度

.roughnessMap : Texture
该纹理的绿色通道用于改变材质的粗糙度。

.roughness : Float
材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。如果还提供roughnessMap,则两个值相乘。

金属

.metalnessMap : Texture
该纹理的蓝色通道用于改变材质的金属度。

.metalness : Float
材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。0.0到1.0之间的值可用于生锈金属的外观。如果还提供了metalnessMap,则两个值相乘。

法线

.normalMap : Texture
用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。 In case the material has a normal map authored using the left handed convention, the y component of normalScale should be negated to compensate for the different handedness.

.normalMapType : Integer
法线贴图的类型。
选项为THREE.TangentSpaceNormalMap(默认)和THREE.ObjectSpaceNormalMap。

纹理加载进度 : loadingManager

  • 统一管理各个加载器
  • 可以传入函数监控所有纹理加载的信息进度
//加载显示器
let div = document.createElement("div");
div.style.width = "200px";
div.style.height = "200px";
div.style.color = "#fff";
div.style.position = "absolute";
div.style.right = "0";
div.style.top = "0";
document.body.appendChild(div);

//加载管理器
const loadingManager = new THREE.LoadingManager(res => {
  console.log("图片加载完成");
}, (url, num, total) => {
  const prograss = ((num / total) * 100).toFixed(2);
  console.log(prograss + "%" + "图片加载进度");
  div.innerHTML = prograss + "%" + "图片加载进度";
}, err => {
  console.log(err + "图片加载出错");
});

//纹理
const textureLoad = new THREE.TextureLoader(loadingManager);
const texture = textureLoad.load("./texture/FabricVelvetEmbossed025/FabricVelvetEmbossed025_COL_2K_METALNESS.png")
const aoMap = textureLoad.load("./texture/FabricVelvetEmbossed025/FabricVelvetEmbossed025_AO_2K_METALNESS.png")
const displacementMap = textureLoad.load("./texture/FabricVelvetEmbossed025/FabricVelvetEmbossed025_ROUGHNESS_2K_METALNESS.png")
const normalMap = textureLoad.load("./texture/FabricVelvetEmbossed025/FabricVelvetEmbossed025_NRM_2K_METALNESS.png")
const matelnessMap = textureLoad.load("./texture/FabricVelvetEmbossed025/FabricVelvetEmbossed025_METALNESS_2K_METALNESS.png")

环境纹理

贴图模式

  • 纹理常量(Texture Constants)
  • 映射模式
    THREE.UVMapping
    THREE.CubeReflectionMapping
    THREE.CubeRefractionMapping
    THREE.EquirectangularReflectionMapping
    THREE.EquirectangularRefractionMapping
    THREE.CubeUVReflectionMapping
    这些常量定义了纹理贴图的映射模式。
    UVMapping是默认值,纹理使用网格的坐标来进行映射。

其它的值定义了环境映射的类型。

  1. CubeReflectionMapping 和 CubeRefractionMapping 用于 CubeTexture —— 由6个纹理组合而成,每个纹理都是立方体的一个面。 对于CubeTexture来说,CubeReflectionMapping是其默认值。

  2. quirectangularReflectionMapping 和 EquirectangularRefractionMapping 用于等距圆柱投影的环境贴图,也被叫做经纬线映射贴图。等距圆柱投影贴图表示沿着其水平中线360°的视角,以及沿着其垂直轴向180°的视角。贴图顶部和底部的边缘分别对应于它所映射的球体的北极和南极。

rgbe模式

//环境纹理
//#region rgbe模式
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("./textures/hdr/002.hdr").then(texture => {
  texture.mapping = THREE.EquirectangularReflectionMapping //设置经纬贴图映射模式
  scence.background = texture;
  scence.environment = texture;
}).catch(err => {
  console.log(err);
})
//#endregion 

cube模式

//#region cube模式
const cubeLoader = new THREE.CubeTextureLoader()
const cubeTexture = cubeLoader.load([
   "./textures/environmentMaps/0/px.jpg",
   "./textures/environmentMaps/0/nx.jpg",
   "./textures/environmentMaps/0/py.jpg",
   "./textures/environmentMaps/0/ny.jpg",
   "./textures/environmentMaps/0/pz.jpg",
   "./textures/environmentMaps/0/nz.jpg",
 ])
 scence.background = cubeTexture;
 scence.environment = cubeTexture;
//#endregion

阴影渲染

灯光阴影
1、材质要满足能够对光照有反应
2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
3、设置光照投射阴影 directionalLight.castShadow = true;
4、设置物体投射阴影 sphere.castShadow = true;
5、设置物体接收阴影 plane.receiveShadow = true;

renderer.shadowMap.enabled = true; 要写在 renderer.render(scence, camera); 之前

你可能感兴趣的:(前端,javascript,前端,js)