渲染 四部曲:
const scence = new THREE.Scene();
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);
width
, height
, depth
);width
— — Width of the sides on the X axis.height
— — Height of the sides on the Y axis.depth
— — Depth of the sides on the Z axis.geometry
,material
)geometry
物体骨架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);
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);
cube.positiom.set();
2.修改x,y,z
cube.postion.x = 1;
verctor3
cube.scale.set(1,2,3);
cube.scale.x = 2;
verctor3
cube.rotaion.set(Eolr());
cube.rotaion.set(Math.PI/4,0,0);
默认传入参数 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;
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 且时钟并未运行,则该方法同时启动时钟。
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()
}
})
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);
.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 );
见文档: 官方的几何体
例子
//纹理
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)
纹理
.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。
//加载显示器
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")
其它的值定义了环境映射的类型。
CubeReflectionMapping 和 CubeRefractionMapping 用于 CubeTexture —— 由6个纹理组合而成,每个纹理都是立方体的一个面。 对于CubeTexture来说,CubeReflectionMapping是其默认值。
quirectangularReflectionMapping 和 EquirectangularRefractionMapping 用于等距圆柱投影的环境贴图,也被叫做经纬线映射贴图。等距圆柱投影贴图表示沿着其水平中线360°的视角,以及沿着其垂直轴向180°的视角。贴图顶部和底部的边缘分别对应于它所映射的球体的北极和南极。
//环境纹理
//#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
//#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); 之前