1 物体Mesh和几何体Geometry
物体Mesh
包含几何体Geometry
和材质Material
网格模型Mesh其实就一个一个三角形(面)拼接构成。使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。
1.1 缓冲类型几何体BufferGeometry
threejs的长方体BoxGeometry
、球体SphereGeometry
等几何体都是基于BufferGeometry类构建的,BufferGeometry是一个没有任何形状的空几何体,可以通过BufferGeometry自定义任何几何形状,具体一点说就是自定义顶点数据。
//创建一个空的几何体对象
const geometry = new THREE.BufferGeometry();
2 几何体的attributes
属性
attributes
存储几何体相关的属性,如:
normal
:法线(法向量)数据geometry.attributes.normal
—— 根据光照方向,好确认折射角position
:顶点三维位置坐标geometry.attributes.position
uv
:顶点二维UV坐标geometry.attributes.uv
2-1 法线 geometry.attributes.normal
数学上的法线概念,比如一个平面,法线的就是该平面的垂线,如果是光滑曲面,一点的法线就是该点切面的法线。
2-1-1 Three.js中法线
Three.js中法线是通过顶点定义,默认情况下,每个顶点都有一个法线数据,就像每一个顶点都有一个位置数据。
// 矩形平面,无索引,两个三角形,6个顶点
// 每个顶点的法线数据和顶点位置数据一一对应
const normals = new Float32Array([
0, 0, 1, //顶点1法线( 法向量 )
0, 0, 1, //顶点2法线
0, 0, 1, //顶点3法线
0, 0, 1, //顶点4法线
0, 0, 1, //顶点5法线
0, 0, 1, //顶点6法线
]);
// 设置几何体的顶点法线属性.attributes.normal
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3);
2-2 几何体顶点位置geometry.attributes.position
2-2-1 BufferAttribute
定义几何体顶点数据
通过javascript类型化数组Float32Array
创建一组xyz坐标数据用来表示几何体的顶点坐标。
//类型化数组创建顶点数据
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
50, 0, 0, //顶点2坐标
0, 100, 0, //顶点3坐标
0, 0, 10, //顶点4坐标
0, 0, 100, //顶点5坐标
50, 0, 10, //顶点6坐标
]);
通过threejs的属性缓冲区对象BufferAttribute表示threejs几何体顶点数据。
// 创建属性缓冲区对象
//3个为一组,表示一个顶点的xyz坐标
const attribue = new THREE.BufferAttribute(vertices, 3);
2-2-2 设置几何体顶点.attributes.position
通过geometry.attributes.position
设置几何体顶点位置属性的值BufferAttribute
。
// 设置几何体attributes属性的位置属性
geometry.attributes.position = attribue;
2-3 顶点UV坐标geometry.attributes.uv
所有的图像文件都是二维的一个平面。水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图像上的任意一个像素。
2-3-1 纹理贴图Texture
纹理贴图就是图片,将纹理贴图应用到几何体的面,或者作为几何体每个面的反射/折射贴图
// load a texture, set wrap mode to repeat
const texture = new THREE.TextureLoader().load( "textures/water.jpg" );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 4, 4 );
2-3-2 在多边形表面上定位纹理贴图
顶点UV坐标的作用是从纹理贴图上提取像素映射到网格模型Mesh的几何体表面上。
多边形为了贴图额外引进了一个UV坐标,以便把多边形的顶点和图象文件上的像素对应起来,这样才能在多边形表面上定位纹理贴图。所以说多边形的顶点除了具有三维的空间坐标外。还具有二维的UV坐标。
UV
这里是指u,v纹理贴图坐标的简称(它和空间模型的X, Y, Z轴是类似的). 它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置.
UV
就是将纹理贴图上每一个点精确对应到模型物体的表面. 在点与点之间的间隙位置由软件进行图像光滑插值处理. 这就是所谓的UV贴图.
2-3-3 纹理贴图UV坐标范围
顶点UV坐标可以在0~1.0之间任意取值,纹理贴图左下角对应的UV坐标是(0,0)
,右上角对应的坐标(1,1)
。
2-3-4 自定义顶点UVgeometry.attributes.uv
顶点UV坐标
geometry.attributes.uv
和顶点位置坐标geometry.attributes.position
是一一对应的,
UV顶点坐标你可以根据需要在0~1之间任意设置,具体怎么设置,要看你想把图片的哪部分映射到Mesh的几何体表面上。
/**纹理坐标0~1之间随意定义*/
const uvs = new Float32Array([
0, 0, //图片左下角
1, 0, //图片右下角
1, 1, //图片右上角
0, 1, //图片左上角
]);
// 设置几何体attributes属性的uv属性
geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2); //2个为一组,表示一个顶点的纹理坐标
2-3-5 获取纹理贴图四分之一
获取纹理贴图左下角四分之一部分的像素值
const uvs = new Float32Array([
0, 0,
0.5, 0,
0.5, 0.5,
0, 0.5,
]);
3. BufferGeometry创建矩形实例
一个矩形平面,可通过两个三角形拼接而成。而且两个三角形有两个顶点的坐标是重合的。
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
80, 0, 0, //顶点2坐标
80, 80, 0, //顶点3坐标
0, 0, 0, //顶点4坐标 和顶点1位置相同
80, 80, 0, //顶点5坐标 和顶点3位置相同
0, 80, 0, //顶点6坐标
]);
// 创建几何体
// const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
const cubeGeometry = new THREE.BufferGeometry()
const vertices = new Float32Array([
1, 1, 1, 1, 1, -1, -1, 1, 1, // 每三个代表一个顶点,三个顶点组成一个面
-1, 1, 1, 1, 1, -1, -1, 1, -1
])
cubeGeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 })
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
3-1 自定义矩形效果
import * as THREE from 'three'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 1、创建场景
const scene = new THREE.Scene()
// 2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
// 设置相机位置
camera.position.set(0, 0, 10)
scene.add(camera)
// 添加物体
// 创建几何体
// const cubeGeometry = new THREE.BoxGeometry(1, 1, 1)
const cubeGeometry = new THREE.BufferGeometry()
const vertices = new Float32Array([
1, 1, 1, 1, 1, -1, -1, 1, 1,
-1, 1, 1, 1, 1, -1, -1, 1, -1
])
cubeGeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 })
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
// 将几何体添加到场景中
scene.add(cube)
console.log(cube)
console.log(cubeGeometry)
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)
// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(3)
scene.add(axesHelper)
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()
4、场景中循环添加多个随机三角形实例
4-1 Three.js颜色对象Color
颜色对象有三个属性,分别为.r
、.g
、.b
,表示颜色RGB的三个分量。
//empty constructor - will default white
const color1 = new THREE.Color();
//Hexadecimal color (recommended)
const color2 = new THREE.Color( 0xff0000 );
//RGB string
const color3 = new THREE.Color("rgb(255, 0, 0)");
const color4 = new THREE.Color("rgb(100%, 0%, 0%)");
//X11 color name - all 140 color names are supported.
//Note the lack of CamelCase in the name
const color5 = new THREE.Color( 'skyblue' );
//HSL string
const color6 = new THREE.Color("hsl(0, 100%, 50%)");
//Separate RGB values between 0 and 1
const color7 = new THREE.Color( 1, 0, 0 );
4-2 Material材质设置透明度
const cubeMaterial = new THREE.MeshBasicMaterial({
// color: color,
transparent: true,
opacity: 0.5
})
4-3 半透明三角形效果
import * as THREE from 'three'
import { Color } from 'three'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 1、创建场景
const scene = new THREE.Scene()
// 2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
// 设置相机位置
camera.position.set(0, 0, 10)
scene.add(camera)
// 添加物体
// 创建几何体
for (let i = 0; i < 50; i++) {
const cubeGeometry = new THREE.BufferGeometry()
const verticesArray = new Float32Array(9) // 必须告诉Float32Array缓冲区设置9个值
// 一个面三个顶点,一个顶点需要3个值,因此一个面共需要9个值
for (let j = 0; j < 9; j++) {
// 顶点坐标的三个坐标值在-5 到 5之间
verticesArray[j] = Math.random() * 10 - 5
}
cubeGeometry.setAttribute(
'position',
new THREE.BufferAttribute(verticesArray, 3)
)
// 每一个三角形颜色随机
const color = new THREE.Color(Math.random(), Math.random(), Math.random())
const cubeMaterial = new THREE.MeshBasicMaterial({
color: color,
transparent: true,
opacity: 0.5
})
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
// 将几何体添加到场景中
scene.add(cube)
}
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement)
// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(3)
scene.add(axesHelper)
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()