Three.js

右手坐标系
// js的坐标系原点在左上角(0,0)转化为原点在屏幕正中心
// 并且右上角的点为(1,1)左上角的点为(-1,-1)
// 如果理解不了可以画个坐标轴感受下
image

const half = {
    width: window.innerWidth / 2,
    height: window.innerHeight / 2
}
window.addEventListener('mouseover', (event) => {
    //坐标轴平移
    //除以 half.width:将范围从 [ -width/2, width/2 ] 映射到 [ -1, 1 ]。
    mouse.x = (event.clientX - half.width) / half.width
    //原来的y轴正方向朝下, 取反
    mouse.y = -(event.clientY - half.height) / half.height
})

// 每秒转一圈 使用gsap可以实现

const clock = new THREE.Clock()
function tick() {
    const time = clock.getElapsedTime()
    mesh.rotation.y = time * Math.PI * 2 //一秒转一圈
    renderer.render(scene, camera)
    window.requestAnimationFrame(tick)
}
tick()

使用OrbitControls可以实现
image

const client = {
    x: 0,
    y: 0
}

canvas.addEventListener('mousemove', (e) => {
    client.x = (e.clientX / sizes.width - 0.5);
    client.y = -(e.clientY / sizes.height - 0.5);
})


const tick = () =>
{
    // Update objects
    // *3增加速度, Math.PI * 2 转一圈,sin() cos()两个组合是个球
    camera.position.x = Math.sin(client.x * Math.PI * 2) * 3;
    camera.position.z = Math.cos(client.x * Math.PI * 2) * 3
    camera.position.y = client.y * 5;
    camera.lookAt(mesh.position)

    // Render
    renderer.render(scene, camera)

    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}

tick()

canvas 可以动态占满可视区

window.addEventListener('resize', () => {
    sizes.width = window.innerWidth
    sizes.height = window.innerHeight
    camera.aspect = sizes.width / sizes.height
    camera.updateProjectionMatrix()
    renderer.setSize(sizes.width, sizes.height)
})

.webgl {
  position: fixed; //隐藏滚动条
  top: 0;
  left: 0;
  overflow: hidden; //隐藏笔记本触摸板上滑底部有白块
}

Sets device pixel ratio. This is usually used for HiDPI device to prevent blurring output canvas.
image
image
image

renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))

双击全屏显示

window.addEventListener('dblclick', () => {
//这个方法有访问限制性 webkitFullscreenElement
    if (!document.fullscreenElement) {
        canvas.requestFullscreen()
    }else{
        document.exitFullscreen()
    }
})

自定义形状

//count 三角形个数,每个三角形3个顶点,每个顶点由(x, y, z)确定
const vertices = new Float32Array(count * 3 * 3)

for (let i = 0; i < count * 3 * 3; i++) {
    vertices[i] = (Math.random() - 0.5)
}
//TypedArray,是个数组,每个顶点怎么确定(x, y, z)--长度为3, 以3分隔开
const positionAttribute = new THREE.BufferAttribute(vertices, 3)
const geometry = new THREE.BufferGeometry()
geometry.setAttribute('position', positionAttribute)

给形状添加纹理

const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('/textures/door/color.jpg')
texture.colorSpace = THREE.SRGBColorSpace //颜色变灰的解决办法

const material = new THREE.MeshBasicMaterial({ map: texture })

metarial:
mesh:
法线的方向:有何用?灯光、反射、折射
image
光相关:
image
阴影支持:
PointLight
DirectionalLight
SpotLight

directionalLight.castShadow = true
//产生阴影的形状
sphere.castShadow = true
//接收阴影
plane.receiveShadow = true
renderer.shadowMap.enabled = true

baking shadow
使用3D软件制作阴影,静态

const bakedShadow = new THREE.TextureLoader().load('/textures/bakedShadow.jpg')
bakedShadow.colorSpace = THREE.SRGBColorSpace

const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(5, 5),
    new THREE.MeshBasicMaterial({
        map: bakedShadow
    })
)

动态,可以移动的阴影

const simpleShadow = new THREE.TextureLoader().load('/textures/simpleShadow.jpg')
simpleShadow.colorSpace = THREE.SRGBColorSpace

const sphereShadow = new THREE.Mesh(
    new THREE.PlaneGeometry(1.5, 1.5),
    new THREE.MeshBasicMaterial({
        color: 0x000000,
        transparent: true,
        alphaMap: simpleShadow
    })
)
sphereShadow.rotation.x = - Math.PI * 0.5
sphereShadow.position.y = plane.position.y + 0.01


tick()方法:
//update the sphere
sphere.position.x = Math.cos(elapsedTime) * 1.5
sphere.position.z = Math.sin(elapsedTime) * 1.5
sphere.position.y = Math.abs(Math.sin(elapsedTime * 3))

//update the shadow
sphereShadow.position.x = sphere.position.x
sphereShadow.position.z = sphere.position.z
sphereShadow.material.opacity = (1 - sphere.position.y) * 0.3

map:
displacementMap:
image
normalMap:
image
aoMap:需要uv

door.geometry.setAttribute('uv2', new THREE.Float32BufferAttribute(door.geometry.attributes.uv.array, 2))

雾:
image

const fog = new THREE.Fog('#262837', 1, 15)
scene.fog = fog
//后面黑色背景雾模糊
renderer.setClearColor('#252837')

粒子:前面粒子遮挡后面粒子的解决方法
image

  1. 边缘处遮挡了后面的粒子
particlesMaterial.alphaTest = 0.001

image
2.

particlesMaterial.depthTest = false

image
缺点:新的geometry前会有粒子
image
3.

particlesMaterial.depthWrite = false

交叉处会变白,多种颜色混合在一起,性能有影响

particlesMaterial.blending = THREE.AdditiveBlending

image
没有使用
image

posted @ 2024-07-04 11:35  躺尸的大笨鸟  阅读(40)  评论(0)    收藏  举报