提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
这段时间没有继续学习,因为清明前公司有个项目把我调到别的项目组帮忙,紧急开发静态页面到甲方展示,上周六加到周三,有点烦躁!还是复习一下纹理的内容 ,以及three.js中各种IPA的应用概念。
课程要点:
1.关于纹理的概念:
METALNESS:金属性创建反射等
normal:法线纹理 与光照有关
AMBIENT OCCLUSION : 灰度图像,伪阴影
ROUGHNESS :粗糙度 与光的消失有关
纹理遵循原则: PBR原则, 物理的渲染(Physically Based Rendering)的缩写
PBR:主要与金属性和粗糙度有关
2.如何加载纹理
TextureLoader // 纹理加载器
需要了解纹理加载的进度?
LoadingManager // 加载管理器 用于管理纹理加载的进度,或状态
方法:onStart onLoad onProgress onError
3.uv展开
概念:纹理放到几何体上不是随机的,坐标什么的都是有人定好的
uv展开之后 会有uv坐标 2*2
这里可以用缓冲几何体,展示 BoxBufferGeometry()
4.当我们生成纹理,放到材质之后
有很多的方法去设置纹理
5.过滤和MIP映射
概念:如果我们放大画面,近距离看我们的立方体,会发现纹理是模糊的,这种发生的现象就是
MIP会发生空间映射,举个例子:GPU对我们的立方体纹理,生成一般的宽高的图片,然后不断重复下去,直到最小值
6.两种算法 缩小过滤器,放大过滤器实现MIP (在纹理中)
minFilter , 默认参数是线性,mipmap,线性滤镜
magFilter ,
用法: minFilter = THREE.NearestFilter
THREE.NearestFilter
THREE.LinearFilter
THREE.NearestMipmapNearestFilter
THREE.NearestMipmapLinearFilter
THREE.LinearMipmapNearestFilter(default)
THREE.LinearMipmapLinearFilter
7.纹理格式和优化
三件事情:纹理的权重,文件的权重,图像的大小,就是分辨率;以及该纹理的数据
前提:
文件的大小:最好更小,更好; 可以通过图片压缩来得到更小的图片 如:TinyPNG
尺寸:GPU能力有限,需要调整纹理,尽可能的小的纹理
数据:数据存储在像素中,我们需要精确的方向,jpg:有损的,png:数据无损的
难点在于找到纹理格式和分辨率的正确组合,不然会有很糟糕的性能,画面等
8.纹理的网站
poliigon.com
3dtexture.me
arroway-textures.ch
9.制作纹理
ps Substance Designer
补充:
你可能会看到我写一些类似PlaneBufferGeometry的东西,而不是PlaneGeometry.
从Three.js的第125个版本开始,那些“缓冲区”几何图形被“非缓冲区”几何图形所取代,你应该在编写它们时去掉Buffer部分。
一、代码
import * as THREE from 'three'
import './style.css'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
/*
Texttures
*/
const LoadingManager = new THREE.LoadingManager()
// LoadingManager.onStart = ()=>{
// console.log('onStart')
// }
// LoadingManager.onLoad = ()=>{
// console.log('onLoad')
// }
// LoadingManager.onProgress = ()=>{
// console.log('onProgress')
// }
// LoadingManager.onError = ()=>{
// console.log('onError')
// }
const textureLoader = new THREE.TextureLoader(LoadingManager)
const colorTexture = textureLoader.load('/textures/checkerboard-8x8.png')
// const colorTexture = textureLoader.load('/textures/door/color.jpg')
const alphaTexture = textureLoader.load('/textures/door/alpha.jpg')
const heightTexture = textureLoader.load('/textures/door/height.jpg')
const normalTexture = textureLoader.load('/textures/door/normal.jpg')
const ambientOcclusionTexture = textureLoader.load('/textures/door/ambientOcclusion.jpg')
const metalnessTexture = textureLoader.load('/textures/door/metalness.jpg')
const roughnessTexture = textureLoader.load('/textures/door/roughness.jpg')
// colorTexture.repeat.x = 2 // repeat 重复属性
// colorTexture.repeat.y = 3
// // colorTexture.wrapS = THREE.RepeatWrapping // 重复s ,会发现向左,重复复制
// // colorTexture.wrapT = THREE.RepeatWrapping // 重复t ,会发现向左,重复复制
// colorTexture.wrapS = THREE.MirroredRepeatWrapping // 重复s ,会发现向左,重复复制
// colorTexture.wrapT = THREE.MirroredRepeatWrapping // 重复t ,会发现向左,反转复制
// colorTexture.offset.x = 0.5 // 偏移量
// colorTexture.offset.y = 0.5
// colorTexture.rotation = Math.PI / 4 // 二维方向上面旋转 想一个立方体,以左下角为点,旋转
// colorTexture.center.x = 0.5 //想象一个圆圈,中间十字,右边点往上向左旋转
// colorTexture.center.y = 0.5 //想象一个圆圈,中间十字,右边点往上向左旋转
// 使用最小过滤器到最近过滤器时,不需要默认MIP,可以关掉 获取性能
colorTexture.generateMipmaps = false
colorTexture.minFilter = THREE.NearestFilter
colorTexture.magFilter = THREE.NearestFilter
/**
* Base
*/
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/**
* Object
*/
const geometry = new THREE.BoxBufferGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ map:colorTexture })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
window.addEventListener('resize', () =>
{
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.x = 1
camera.position.y = 1
camera.position.z = 1
scene.add(camera)
// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
/**
* Animate
*/
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
二、知识点
1.复习一下
上述代码中主要用到的是scene,camera,controls,material,mesh,geometry,render,texture
其中需要配合js进行监听resize 屏幕的尺寸变化,同时获取屏幕的尺寸进行自适应;需要配合requestAnimationFrame进行回调;但是由于camera,也需要自适应更新,需要在监听中执行这个方法updateProjectionMatrix,同时需要渲染器重新触发。
// 屏幕自适应
window.addEventListener('resize',()=>{
// Update sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// Update camera
camera.aspect = sizes.width / sizes.height
camera.updateProjectionMatrix()
// Update renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
2.Texture
概念:我们需要了解一些纹理的概念,
METALNESS:金属性创建反射等
normal:法线纹理 与光照有关
AMBIENT OCCLUSION : 灰度图像,伪阴影
ROUGHNESS :粗糙度 与光的消失有关
上述概念根据我的理解应该是各种物体表面的颜色,说实话看到这有点蒙!
2.1 PBR原则
关于这个原则 纹理遵循原则: PBR原则, 物理的渲染(Physically Based Rendering)的缩写
PBR 主要和金属性和粗糙度
2.2 如何加载纹理
TextureLoader // 纹理加载器 设想一种场景就是我有了立方体,但是它需要皮肤 (图片需要自己找)
用法:
// 纹理 Textrue
const textureLoader = new THREE.TextureLoader(LoadingManager)
const colorTexture = textureLoader.load('/textures/checkerboard-8x8.png')
const material = new THREE.MeshBasicMaterial({map:colorTexture})
我想知道纹理加载的进度怎么办
LoadingManager // 纹理加载状态
onStart,onLoad,onProgress,onError
我可以设置一些关于纹理的设置
// 关于纹理位置 旋转等属性的操作
// colorTexture.repeat.x = 2
// colorTexture.repeat.y = 2
// colorTexture.wrapS = THREE.RepeatWrapping // 重复s
// colorTexture.wrapT = THREE.RepeatWrapping
// colorTexture.offset.x = 0.5 //偏移量
// colorTexture.offset.y = 0.5
// colorTexture.rotation = Math.PI / 4 // 二维方向上面旋转
// colorTexture.center.x = 0.5
// colorTexture.center.y = 0.5
2.3 uv展开
概念:纹理放到几何体上不是随机的,坐标什么的都是有人定好的
uv展开之后 会有uv坐标 2*2
这里可以用缓冲几何体,展示 BoxBufferGeometry()
4.当我们生成纹理,放到材质之后
有很多的方法去设置纹理
2.4 过滤和MIP映射
概念:如果我们放大画面,近距离看我们的立方体,会发现纹理是模糊的,这种发生的现象就是
MIP会发生空间映射,举个例子:GPU对我们的立方体纹理,生成一般的宽高的图片,然后不断重复下去,直到最小值
2.5 缩小过滤器,放大过滤器实现MIP (在纹理中)
minFilter , 默认参数是线性,mipmap,线性滤镜
magFilter
colorTexture.generateMipmaps = false
colorTexture.minFilter = THREE.NearestFilter
colorTexture.magFilter = THREE.NearestFilter
让我们换一个图,看一下没有设置和设置之后的显示
可以看到设置之后会更清晰,物体如刀削般锋利!
2.6 纹理格式和优化
三件事情:纹理的权重,文件的权重,图像的大小,就是分辨率;以及该纹理的数据
前提:
文件的大小:最好更小,更好; 可以通过图片压缩来得到更小的图片 如:TinyPNG
尺寸:GPU能力有限,需要调整纹理,尽可能的小的纹理
数据:数据存储在像素中,我们需要精确的方向,jpg:有损的,png:数据无损的
难点在于找到纹理格式和分辨率的正确组合,不然会有很糟糕的性能,画面等
补充:
你可能会看到我写一些类似PlaneBufferGeometry的东西,而不是PlaneGeometry.
从Three.js的第125个版本开始,那些“缓冲区”几何图形被“非缓冲区”几何图形所取代,你应该在编写它们时去掉Buffer部分。
总结
容易忘,都是英文单词,还是要多练习!不然根本不知道用什么方法,只能百度。