//1、创建场景
const scene = new THREE.Scene()
//2、创建网格模型
const geometry = new THREE.BoxGeometry(100,100,100)
const matrial = new THREE.MeshLambertMaterial({
color: #0000ff
})
const mesh = new THREE.Mesh(geometry,matrial)
scene.add(mesh)
//3、添加光照
const point = new THREE.PointLight(0xffffff)
point.position.set(10,20,30)
scene.add(point)
const ambient = new THREE.ambient(0x444444)
scene.add(ambient)
//设置相机
const width = window.innerWidth
const height = window.innerHeight
const aspect = width/height
const s = 20
//参数为左右上下近远
const camera = new THREE.OrthographicCamera(-s*aspect,s*aspect,s,-s,1,1000)
camera.position.set(10,10,10)
camerta.lookAt(camera.position)
//设置渲染器对象
const renderer = new THREE.WebGLRenderer()
renderer.setSize(width.height)
renderer.setClearcolor(0x,fffffff,1)
document.body.appendChild(renderer.domElement)
renderer.renderer(scene,camera)
const controls = new THREE.OrbitControls(camera,renderer.domElement)
controls.addEventListener('change',render) //自动监听鼠标键盘事件,更新相机参数
//如果使用requestAnimationFrame调用render函数,则不需要添加监听事件
new THREE.MeshlambertMatrial({
color: 0xff0000,
opacity: 0.7,
transparent: true
})
//也可以以对象方式设置
material.opacity = 0.7
ambient
:环境色,于与AmbientLight光源一起使用颜色会相乘emissive
:材质发射的亚瑟,不受其他光照影响的颜色specular
:光亮程度及高光部分颜色shininess
:指定高光部分的亮度new THREE.MeshPhongMaterial({
color: #ffffff,
specular: 0x4488ee,
shininess: 12
})
MeshLambertMaterial
:lambert网格材质,与光照有反应,漫反射MeshBasicMaterial
:基础网格材质,不受光照影响MeshPhongMaterial
:高光phong材质,与光照有反应MeshStandradMaterial
:PBR物理材质,可以更好模拟玻璃、金属等效果光源类型:
AmbientLight
:环境光PointLight
:点光源DirectionlLight
:平行光SpotLight
:聚光源注:如果只使用环境光,整个立方体没有任何棱角感,必须设置具有方向性的点光源和平行光源
//创建顶点数据缓冲区
const geometry= new THREE.BufferGeometry()
//创建顶点坐标
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
50, 0, 0, //顶点2坐标
0, 100, 0, //顶点3坐标
])
const attribute = new THREE.BufferAttribute(vertices,3)
geometry.attributes.position = attribute
const material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: ThREE.DoubleSide,
})
const mesh = new THREE.Mesh(geometry,material)
const material = new THREE.PointsMaterial({
color: 0x0000ff,
size: 10.0,
})
const points = new THREE.Points(geometry,material)
const material = new THREE.LineBasicMaterial({
color: 0x0000ff,
})
const line = new THREE.Line(geometry,material)
const colors = new Float32Array([
1, 0, 0, //顶点1颜色
0, 1, 0, //顶点2颜色
0, 0, 1, //顶点3颜色
1, 1, 0, //顶点4颜色
0, 1, 1, //顶点5颜色
1, 0, 1, //顶点6颜色
]);
geometry.attributes.color = new THREE.BufferAttribute(colors,3)
const material = new THREE.PointsMaterial({
vertexColor: THREE.VertexColor,
size: 10.0
})
const points = new THREE.Points(geometry,material)
scene.add(points)
定义顶点法向量后点光源和平行光源会起作用
var normals = new Float32Array([
0, 0, 1, //顶点1法向量
0, 0, 1, //顶点2法向量
0, 0, 1, //顶点3法向量
0, 1, 0, //顶点4法向量
0, 1, 0, //顶点5法向量
0, 1, 0, //顶点6法向量
]);
geometry.attributes.normal = new THREE.BufferAttribute(normals,3)
当我们画一个长方形时,需要6个顶点数据,然而其中两个顶点可以复用,因此通过索引来实现复用
const index = new Uint16Array([
0,1,2,
0,2,3,
])
geometry.index = new THREE.BufferAttribute(index,1)
const geometry = new THREE.Geometry()
const p1 = new THREE.Vector3(50,0,0)
const color1 = new THREE.Color(0x00ff00)
//将顶点数据添加到geometry对象中
geometry.vertices.push(p1)
geometry.colors.push(color1) //设置顶点颜色属性对Mesh无效
//设置顶点颜色数据时,需要将vertexColor变为THREE.VertexColors
const material = new THREE.MeshLambertMaterial({
vertexColor: THREE.VertexColors,
side: DoubleSide,
})
设置三角形Face3的颜色对于Mesh模型有效,对于Points、Line无效
var p1 = new THREE.Vector3(0, 0, 0); //顶点1坐标
var p2 = new THREE.Vector3(0, 100, 0); //顶点2坐标
var p3 = new THREE.Vector3(50, 0, 0); //顶点3坐标
var p4 = new THREE.Vector3(0, 0, 100); //顶点4坐标
geometry.vertices.push(p1,p2,p3,p4)
//构建一个三角面
const face1 = new THREE.Face3(0,1,2)
//每个顶点的法向量
var n1 = new THREE.Vector3(0, 0, -1);
var n2 = new THREE.Vector3(0, 0, -1);
var n3 = new THREE.Vector3(0, 0, -1);
face1.vertexNormals.push(n1,n2,n3)
const face2 = new THREE.Face3(0,2,3)
face2.normal = new ThREE.Vector3(0,-1,0)
//设置颜色
face1.color = new THREE.Color(0x00f0f0f)
face1.vertexColors = [
new THREE.Color(0x00f0f0f),
new THREE.Color(0x00f0f0f),
new THREE.Color(0x00f0f0f),
]
geometry.faces.push(face1,face2)
BoxGeometry
、PlaneGeometry
、SphereGeometry
的基类为Geometry
//获取几何体的顶点位置数据
const vertex_position = geometry.vertices
//获取几何体的面数据
const face_data = geometry.faces
//获取几何体的颜色数据
const colors = geometry.colors
BoxBufferGeometry
、PlaneBufferGeometry
、SphereBufferGeometry
的基类为BufferGeometry
//获取顶点位置
const vertex = geometry.attributes.position
//顶点颜色
const colors = geometry.attributes.color
//顶点法向量
const normal = geometry.attributes.normal
//纹理贴图UV坐标
const uv = geometry.attributes.ub
//顶点索引数据
const index = geometry.index
网格模型进行变换不会影响几何体的顶点位置坐标,网格模型旋转缩放平移改变的是模型的本地矩阵、世界矩阵
geometry.scale(2,2,2)
geometry.translate(50,0,0)
geometry.rotateX(Math.PI/4)
geometry.center()
(1)side属性
定义面的渲染方式,可以是前面(THREE.FrontSide)、后面(THREE.BackSide)、双面(THREE.DoubleSide)
(2)材质透明度:opacity、transparent
对网格模型的几何体进行缩放时,克隆的网格也会同时改变大小;几何体的克隆或复制为深拷贝
漫反射光的颜色
=网格模型材质颜色
x 光线颜色
x 光线入射角余弦值
scene作为group的父级,group作为mesh1和mesh2的父级,这样对group做的任何操作都会同样作用在mesh1和mesh2上
const group = new THREE.Group()
group.add(mesh1)
group.add(mesh2)
scene.add(group)
//访问子对象
const child = scene.children || group.children
//移除子对象
group.remove(mesh1.mesh2)
(1)几何体
(2)曲线
(1)圆弧线
//参数分别为圆心坐标、圆弧半径、起始角度、是否顺时针绘制
const arc = new THREE.ArcCurve(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise)
const points = arc.getPoints(50) //返回51个顶点
(2)setFromPoints方法
Geometry使用该方法可以把数组points中顶点数据提取出来赋值给几何体的顶点位置属性geometry.vertices,BufferGeometry和Geometry一样具有该方法,不过提取顶点后的数据赋值给geometry.attributes.position属性
const geometry = new THREE.Geometry()
const curve = new THREE.
const points = [
new THREE.Vector2(-50, -50),
new THREE.Vector2(-60, 0),
new THREE.Vector2(0, 50),
new THREE.Vector2(60, 0),
new THREE.Vector2(50, -50),
new THREE.Vector2(-50, -50),
]
const shape = new THREE.Shape(points)
const geometry = new THREE.ShapeGeometry(shape,20)
//生成外接圆
const shape = new THREE.Shape()
shape.absarc(0,0,100,0,2*Math.PI)
const geometry = new THREE.ShapeGeometry(shape,20)
//
//依靠点生成二维路径
const shape = new THREE.Shape()
const path = new THREE.Path(points)
//移动基点
path.moveTo()
//从currentPosition连线到改点
path.lineTo()
//绘制圆弧
path.arc(x,y,r,startAngle,endAngle,closewise)
//添加到形状的内轮廓中
shape.holes.push(path)
const geometry = new THREE.ExtrudeGeometry(shape,{
amount: 120, //拉伸长度
bevelEnabled: false //无倒角
})
const material = new THREE.PointsMaterial({
color: 0x0000ff,
size: 5.0
})
const mesh = new THREE.Points(geometry,material)
扫描效果与拉伸一致,不过不需要设置拉伸距离,设置扫描路径即可
const curve = new THREE.SplineCurve3([
new THREE.Vector3( -10, -50, -50 ),
new THREE.Vector3( 10, 0, 0 ),
new THREE.Vector3( 8, 50, 50 ),
new THREE.Vector3( -5, 0, 100)
])
const geometry = new THREE.ExtrudeGeometry(shape,{
bevelEnabled: false,
extrudePath: curve, //扫描轨迹
steps:55//扫描方向细分数
})
将图片作为geometry的贴图,需要设置material的map属性为相应的geometry
const geometry = new THREE.PlaneGeometry(204,102)
//设置纹理对象
const textureLoader = new THREE.TextureLoader()
textureLoader.load('./1.png',(texture)=>{
const material = new THREE.MeshLambertMaterial({
map: texture
})
const mesh = new THREE.Mesh(geometry,material)
})
也可以使用ImgLoader,内部使用FileLoader来加载文件,并被CubeTextureLoader、ObjectLoader、TextureLoader所使用
const loader = new THREE.ImageLoader()
loader.load('./1.png',(image)=>{
const texture = new THREE.Texture(image)
//下次使用纹理时触发更新
texture.needsUpdate = true
})
const geometry = new THREE.BufferGeometry()
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
80, 0, 0, //顶点2坐标
80, 80, 0, //顶点3坐标
0, 80, 0, //顶点4坐标
])
//创建缓冲区对象
const attribute = new THREE.BufferAttribute(vertices,3)
geometry.attributes.position = attribute
const normals = new Float32Array([
0, 0, 1, //顶点1法向量
0, 0, 1, //顶点2法向量
0, 0, 1, //顶点3法向量
0, 0, 1, //顶点4法向量
])
geometry.attributes.normal = new THREE.BufferAttribute(normals,3)
const index = new Uint16Array([0,1,2,0,2,3])
geometry.index = new THREE.BufferAttribute(index,1)
const uvs = new Float32Array([
0,0, //图片左下角
1,0, //图片右下角
1,1, //图片右上角
0,1, //图片左上角
])
geometry.attributes,uv = new THREE.BufferAttribute(uvs,2)
(1)数组材质
const material_1 = new THREE.MeshPhongMaterial({
color: 0xff0000
})
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.loader('./1.png')
const material_2 = new THREE.MeshLambertMaterial({
map: texture
})
const materialArr = [material_2,material_1,material_1,material_1,material_1,material_2]
const mesh = new THREE.Mesh(geometry,materialArr)
scene.add(mesh)
(2)材质索引属性
geometry.faces[1].materialIndex = 1
(1)阵列
wrapS:纹理贴图在水平方向上将如何包裹
wrapT:纹理贴图在垂直方向上将如何包裹
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.repeat.set(4,2)
(2)偏移
相对于原来位置进行偏移
texture.offset = new THREE.Vector2(0.5,0.5)
(3)旋转
texture.rotation = Math.PI/4
texture.center.set(0.5,0.5)
const textureLoader = new THREE.TextureLoader()
const textureNormal = textureLoader.load('./1.png')
const material = new THREE.MeshPhongMaterial({
color: 0x0000ff,
normalMap: textureNormal,
normalScale: new THREE.Vector2(3,3)
})
设置material的bumpMap属性为纹理贴图,bumpScale为凹凸的高度
const material = new THREE.MeshPhongMaterial({
shininess: 30
map: texture,
specular: textureSpecular, //高光贴图
})
类似于租房的VR效果
const geometry = new THREE.BoxGrometry(100,100,100)
const loader = new THREE.CubeTextureLoader()
loader.setPath('./')
const cubeTexture = loader.load(['1.jpg','1.jpg','1.jpg','1.jpg','1.jpg','1.jpg'])
const material = new THREE.MeshPhongMaterial({
envMap: cubeTexture
})
(3)相机位置和拍摄方向
camera.position.set()
camera.lookAt(scene.position)
如果浏览器窗口尺寸发生变化,会出现局部空白区域
//相当于设置视图矩阵的matrixWorldInverse属性
camera.position.set()
camera.lookAt()
//相当于设置投影矩阵的projectionMatrix属性
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
(1)正射投影相机自适应渲染
需要重新设置相机对象和渲染对象参数
window.onresize = ()=>{
renderer.setSize(window.innerWidth,window.innerHeight)
k = window.innerWidth/window.innerHeight
camera.left = -s*k
camera.right = s*k
camera.top = s
camera.bottom = -s
//需要手动更新,这是用为每次执行渲染器方法render的时候不会读取相机相关参数重新计算一次投影矩阵
//如果相机的一些属性发生了变化,需要执行updateProjectMatrix方法更新相机的投影矩阵
camera.updateProjectionMatrix()
}
(2)透视相机自适应渲染
window.onresize = ()=>{
renderer.setSize(window.innerWidth,window.innerHeight)
camera.aspect = window.innerWidth/window.innerHeight
camera.updateProjectionMatrix()
}