threeJs学习笔记(三)

1.环境贴图

目的:在物体贴上四周环境在物体上的反射画面内容,其实还是贴图

初始化环境(utils/init.js)

// 初始化 three.js 基础环境
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
export let scene, camera, renderer, controls;

(function init() {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  camera.position.set(0, 0, 5)
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)

  app.appendChild(renderer.domElement)
})();

(function createControls() {
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
})();

(function createHelper() {
  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)
})();

(function resizeRender() {
  window.addEventListener('resize', () => {
    renderer.setSize(window.innerWidth, window.innerHeight)
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
  })
})();

(function renderLoop() {
  renderer.render(scene, camera)
  controls.update()
  requestAnimationFrame(renderLoop)
})();

import { scene } from './utils/init'
import * as THREE from 'three'
// import * as dat from 'dat.gui'


function initBase() {
  // const geometry = new THREE.SphereGeometry(1, 32, 16)

  // 1. 使用 CubeTextureLoader (立方体纹理加载器)- 6 个面的图片,得到纹理对象
  const cubeTL = new THREE.CubeTextureLoader()
  const cubeTexture = cubeTL.setPath('image/sky/').load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])

  // const material = new THREE.MeshStandardMaterial({
  //   // 2. 设置给物体的 envMap 环境贴图属性
  //   envMap: cubeTexture,
  //   roughness: 0,
  //   metalness: 1
  // })

  // 3. 借助 GUI 工具,修改物体材质的粗糙度和金属度观察效果
  // const gui = new dat.GUI()
  // gui.add(material, 'roughness', 0, 1, 0.1)
  // gui.add(material, 'metalness', 0, 1, 0.1)

  // 天空盒子-scene 场景添加一个背景
  scene.background = cubeTexture

  // const mesh = new THREE.Mesh(geometry, material)
  scene.add(mesh)
}

initBase()

2.认识模型文件并使用

目的:建模师建好的模型物体,可以通过 three.js 提供的加载器,加载到网页中显示此物体和操作

import { scene } from './utils/init'
import * as THREE from 'three'
// 1. 引入加载 gltf/glb 模型文件的加载器
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'

function initBase() {
  // 2. 引入public文件下的model的ferrari.glb文件,实例化加载器并加载模型文件:load() 异步
  new GLTFLoader().load('model/ferrari.glb', gltf => {
    // 3. 取出模型对象并添加到场景中
    const model = gltf.scene
    // 遍历物体内部每个小物体组成
    model.traverse(obj => {
      console.log(obj)
    })
    scene.add(model)
  })
}

function createLight() {
  const light = new THREE.AmbientLight(0xffffff, 1)
  scene.add(light)
}

initBase()
createLight()

借助 three.js 网页提供的模型.编辑器,查找建模师的模型中某个小物体名字,并回扣应用到代码里操作修改自己网站中的这个模型效果 。

打开网址:three.js editor

可导入对应的模型文件进行操作

3.光源-环境光

环境光:没有方向,不能投射阴影,只能照亮物体,但是没有光斑

 注意1:没有方向,不能投射阴影,只能照亮物体,没有光斑

 注意2:金属度1,粗糙度0,无环境贴图,放射颜色为黑色,物体自身为黑色并不是灯光的问题

import { scene, camera } from './utils/init'
import * as THREE from 'three'


function createFloor() {
  // 1. 创建平面缓冲几何体
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  scene.add(plane)
}
function createLight() {
  // 2. 创建环境光
  const light = new THREE.AmbientLight(0xffffff, 1)
  scene.add(light)
}

camera.position.set(5, 5, 5)
createFloor()
createLight()

4.光源-点光源

从一个点向各个方向发射的光源。模拟灯泡发出的光。有方向可投射阴影和光斑

import { scene, camera } from './utils/init'
import * as THREE from 'three'

function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  scene.add(plane)
}
function createLight() {
  // 点光源(灯泡)
  const light = new THREE.PointLight(0xffffff, 1, 100);
  light.position.set(3, 3, 3);
  scene.add(light);

  const pointLightHelper = new THREE.PointLightHelper(light, 1);
  scene.add(pointLightHelper);
}

camera.position.set(5, 5, 5)
createFloor()
createLight()

5.光源-平行光

沿着特定方向发射的光线。模拟太阳光,太阳足够远,因为我们认为太阳光是平行的。

import { scene, camera } from './utils/init'
import * as THREE from 'three'

function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  scene.add(plane)
}
function createLight() {

  // 平行光(太阳)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  scene.add(directionalLight);

  const helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);
}

camera.position.set(5, 5, 5)
createFloor()
createLight()

6.光源-聚光灯

从一个点沿一个方向射出,距离越远,光锥尺寸越大,模拟手电筒/舞台聚光灯

 

import { scene, camera } from './utils/init'
import * as THREE from 'three'

function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  scene.add(plane)
}
function createLight() {

  // 聚光灯(手电)
  const spotLight = new THREE.SpotLight(0xffffff, 1);
  spotLight.position.set(3, 3, 3);
  // 灯光的纹理(会把图片和聚光灯颜色混合后打在目标物体上)
  spotLight.map = new THREE.TextureLoader().load('image/desert.jpg');
  scene.add(spotLight)

  const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  scene.add(spotLightHelper);
}

camera.position.set(5, 5, 5)
createFloor()
createLight()

  7.灯光与阴影

每个光特点不同,产生的光斑和阴影不相同

名字构造函数特点产生阴影/光斑
环境光AmbientLight照亮所有受光照影响物体无方向,不产生
点光源PointLight一个点向四周发射光线(灯泡)有方向,能产生
平行光DirectionalLight平行发射光线(太阳光)有方向,能产生
聚光灯SpotLight一个点向一个方向散射光线(手电筒/舞台灯)有方向,能产生
import { scene, camera, renderer } from './utils/init'
import * as THREE from 'three'

function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  plane.receiveShadow = true
  scene.add(plane)
}
function createLight() {
  // 聚光灯(手电)
  const spotLight = new THREE.SpotLight(0xffffff, 1);
  spotLight.position.set(13, 13, 13);
  // spotLight.map = new THREE.TextureLoader().load('image/desert.jpg');

  spotLight.castShadow = true // 灯光产生阴影

  // 让聚光灯打出阴影贴图大小(2 的几次幂值)
  spotLight.shadow.mapSize.width = 2048;
  spotLight.shadow.mapSize.height = 2048;
  
  scene.add(spotLight)

  const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  scene.add(spotLightHelper);
}
function createSphere() {
  const geometry = new THREE.SphereGeometry(1, 32, 16)
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff00
  })
  const mesh = new THREE.Mesh(geometry, material)
  mesh.position.set(0, 1, 0)
  mesh.castShadow = true // 物体产生阴影(参与阴影计算)
  scene.add(mesh)
}

camera.position.set(5, 5, 5)
renderer.shadowMap.enabled = true // 开启阴影渲染支持
createLight()
createSphere()
createFloor()

8.gsap 动画库

基于 gsap 第三方库实现动画效果

使用步骤:

1.下载并引入 gsap 动画库

2.使用 gsap.to() 设置动画

3.根据文档调整动画相关效果

import { scene, camera, renderer } from './utils/init'
import * as THREE from 'three'
// 1. 下载并引入 gsap 动画库
import gsap from 'gsap'

let sphere // 球体对象
let helper // 平行光辅助对象
function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  plane.receiveShadow = true
  scene.add(plane)
}
function createLight() {
  // 平行光(太阳)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  directionalLight.castShadow = true
  directionalLight.target = sphere
  scene.add(directionalLight);

  helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);

}
function createSphere() {
  const geometry = new THREE.SphereGeometry(1, 32, 16)
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff00
  })
  sphere = new THREE.Mesh(geometry, material)
  sphere.position.set(0, 1, 0)
  sphere.castShadow = true
  scene.add(sphere)
}
function initAnimation() {
  // 2. 使用 gsap.to() 做一个补间动画
  // 参数1:标签选择器/DOM对象/物体对象
  // 参数2:动画相关配置项
  const aniObj = gsap.to(sphere.position, {
    // 3. 根据文档调整相关效果
    x: 5, // 对参数 1 目标对象做什么属性的变化
    duration: 3, // 动画持续时间
    delay: 2, // 延迟 2 秒后在做当前动画
    repeat: -1, // 无限次反复运动
    yoyo: true, // 回到原点过程也有一个动画
    ease: "expo.out", // 设置缓冲效果(参考: https://greensock.com/docs/v3/Eases)调整使用的内置字符串模式
    onStart() {
      console.log('开始动画')
    },
    onUpdate() {
      console.log('动画更新')
      helper.update() // 让平行光辅助对象可以实时更新角度和射线
    },
    onComplete() {
      console.log('动画结束')
    }
  })
  // 补充:控制动画暂停/恢复
  window.addEventListener('dblclick', () => {
    if (aniObj.isActive()) {
      // 当前动画运行中为 true
      aniObj.pause()
    } else {
      // 暂停->恢复
      aniObj.resume()
    }
  })
}

camera.position.set(5, 5, 5)
renderer.shadowMap.enabled = true

createSphere()
createFloor()
createLight()
initAnimation()

9.CSS2D 渲染器

把原生 DOM 标签转换到空间中,作为一个 2D 物体加载显示

CSS3D与CSS2D 区别:

 CSS3D:始终不面向摄像机,场景缩放时跟随着变大/变小,不被模型遮挡,通过 DOM 事件点击

 CSS2D:始终面向摄像机,  场景缩放时不跟随变化,     不被模型遮挡,通过 DOM 事件点击

import { scene, camera, renderer } from './utils/init2d'
import * as THREE from 'three'
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';


let sphere 
let helper 
function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  plane.receiveShadow = true
  scene.add(plane)
}
function createLight() {
  // 平行光(太阳)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  directionalLight.castShadow = true
  directionalLight.target = sphere
  scene.add(directionalLight);

  helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);

}
function createSphere() {
  const geometry = new THREE.SphereGeometry(1, 32, 16)
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff00
  })
  sphere = new THREE.Mesh(geometry, material)
  sphere.position.set(0, 1, 0)
  sphere.castShadow = true
  scene.add(sphere)
}
function create2d() {
  const div = document.createElement('div')
  div.innerHTML = '球体'
  div.style.color = 'red'
  div.style.fontSize = '32px'
  // 与 CSS3D 区别:2D 物体 px 像素单位还可以生效,而不是平移到三维空间中的单位

  const object2d = new CSS2DObject( div )
  object2d.position.set(0, 3, 0)
  scene.add(object2d)
}


camera.position.set(5, 5, 5)
renderer.shadowMap.enabled = true

createSphere()
createFloor()
createLight()
create2d()

 10three.js 精灵物体

精灵(Sprite)物体:精灵是一个总面朝摄像机的平面,通常使用一个半透明的纹理

import { scene, camera, renderer } from './utils/init2d'
import * as THREE from 'three'
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';

let sphere
let helper
function createFloor() {
  const geometry = new THREE.PlaneGeometry(10, 10)
  const material = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    side: THREE.DoubleSide
  })
  const plane = new THREE.Mesh(geometry, material)
  plane.rotation.set(- Math.PI / 2, 0, 0)
  plane.receiveShadow = true
  scene.add(plane)
}
function createLight() {

  // 平行光(太阳)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(3, 3, 3);
  directionalLight.castShadow = true
  directionalLight.target = sphere
  scene.add(directionalLight);

  helper = new THREE.DirectionalLightHelper(directionalLight, 1);
  scene.add(helper);
}
function createSphere() {
  const geometry = new THREE.SphereGeometry(1, 32, 16)
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff00
  })
  sphere = new THREE.Mesh(geometry, material)
  sphere.position.set(0, 1, 0)
  sphere.castShadow = true
  scene.add(sphere)
}
function create2d() {
  const div = document.createElement('div')
  div.innerHTML = '球体'
  div.style.color = 'red'
  div.style.fontSize = '32px'
  // 与 CSS3D 区别:2D 物体 px 像素单位还可以生效,而不是平移到三维空间中的单位

  const object2d = new CSS2DObject(div)
  object2d.position.set(0, 3, 0)
  scene.add(object2d)
}
function createSprite() {
  // 使用:
  // 1. 准备纹理对象并加载图片素材
  const texture = (new THREE.TextureLoader()).load('image/pkq.jpg')
  // 2. 使用 SpriteMaterial 精灵材质
  const material = new THREE.SpriteMaterial({ map: texture })
  // 3. 使用 Sprite 创建精灵物体并加入场景
  const sprite = new THREE.Sprite(material)
  sprite.position.set(3, 0.5, -3)
  scene.add(sprite)
}


camera.position.set(5, 5, 5)
renderer.shadowMap.enabled = true

createSphere()
createFloor()
createLight()
create2d()
createSprite()

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值