threejs-材质
文章目录
前言
threejs材质讲解:材质常用属性,材质种类,效果示例
材质的常用属性
基础属性
id // 标识符,创建时自增
uuid // 唯一标识
name // 材质名称
opacity // 不透明度,[0,1],transpant为true时生效
transpant // bool
overdraw // 过度描绘
visible // 是否可见
side // 侧面,定义为哪一面使用材质:Three.FrontSide,Three.BackSide,Three.DoubleSide
needsUpdate // bool,为true时,使用最新的材质属性而不是缓存
colorWrite // bool,为true时,不会输出真实的颜色
flatShading // bool,平面着色,为flase时光照效果更加平滑
lights // bool,为true时接收光照
dithering // bool,开启时使用颜色抖动
shadowSide // 产生投影的面,与side对应的面相反
vertexColors // 顶点颜色
fog // bool,雾化效果
融合属性
渲染的颜色与背景交互的方式
blending // 材质与背景融合的方式
blendSrc // 融合源
blendDst // 融合目标
blendequation // 融合人透明度,结blendSrc,blendDst自定义融合方式
blendSrcAplha // 为 blendSrc指定透明度
blendDstAplha // 为 blendDst指定透明度
高级属性
WebGL底层相关的一些参数,不常用
depthTest //
depthWrite //
depthFunc //
alphstest //
precision //
常用的材质
MeshBasicMaterial()
一个以简单着色(平面或线框)方式来绘制几何体的材质。不受光照影响
- 具备一些自有属性
color // 颜色
wireframe // bool,将材质渲染成线框,对调试有利
wireframeLinewidth // 开启wireframe时,定义线框中线的宽度
(线框线宽)
这个属性
wireframeLinecap // 开启wireframe时,定义线框模式下顶点间线段的端点如何显示。可选值包括 butt(平)、round(圆)和 square(方)
wireframeLinejoin //定义线段的连接点如何显示。可选的值包括 round、bevel(斜角)和 miter(尖角)。
MeshDepthMaterial()
按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远,可以通过相机的near属性和far属性之间的差距决定场景的亮度和物体消失的速度。
联合材质createMultiMaterialObject ( geometry, materials: Array )
需要借助SceneUtils这个外部工具包
- geometry 几何体
- materials 材质数组
举例
const cubeGeometry = new THREE.BoxGeometry(10, 10, 10);
// 定义要联合的两种材质
const cubeMaterial = new THREE.MeshDepthMaterial();
const colorMaterial = new THREE.MeshBasicMaterial({
color: controls.color,
transparent: true, // 当材质为MeshBasicMaterial时,需要设置,否则会出现一个纯色物体
blending: THREE.MultiplyBlending
});
const cube = new THREE.SceneUtils.createMultiMaterialObject(
cubeGeometry,
[
colorMaterial,
cubeMaterial
]);
cube.children[1].scale.set(0.99, 0.99, 0.99); // 防止画面闪烁
cube.castShadow = true;
scene.add(cube);
createMultiMaterialObject函数创建一个网格的时候,几何体会被复制,返回一个Group,里面两个网格完全相同,分布被赋予不同的材料。通过缩小MeshDepthMaterial材质的网格,就可以避免画面闪烁。方法如下:
cube.children[1].scale.set(0.99, 0.99, 0.99);
法线材质MeshNormalMaterial()
把法向量映射到RGB颜色的材质
Lambert材质MeshLambertMaterial()
该材质使用基于非物理的Lambertian模型来计算反射率。 这可以很好地模拟一些表面(例如未经处理的木材或石材),但不能模拟具有镜面高光的光泽表面(例如涂漆木材)
Phong材质MeshPhongMaterial()
该材质使用非物理的Blinn-Phong模型来计算反射率。 该材质可以模拟具有镜面高光的光泽表面(例如涂漆木材)
标准格材质MeshStandardMaterial()
使用物理上正确的模型计算表面材质与光照的互动。能够更好地表现塑料质感和金属质感
物理材质MeshPhysicalMaterial()
MeshStandardMaterial的扩展,能够更好地控制反射率
线材质LineMaterial()
一种用于绘制线框样式几何体的材质
效果示例
场景搭建见链接 threejs-场景创建(基于react-hooks)
const createGeo = () => {
/**
* 创建两个法向量材质的球和立方体
*/
const sphereGeometry = new THREE.SphereGeometry(5, 20, 20);
const cubeGeometry = new THREE.BoxGeometry(10, 10, 10);
const meshMaterial = new THREE.MeshNormalMaterial();
const sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
const cube = new THREE.Mesh(cubeGeometry, meshMaterial);
sphere.position.set(-40, 20, 0);
cube.position.set(-20, 20, 0);
sphere.castShadow = true;
cube.castShadow = true;
scence.add(sphere);
scence.add(cube);
/**
* 创建一个指定材质的立方体
*/
const group = new THREE.Mesh();
// add all the rubik cube elements
const mats = [
new THREE.MeshBasicMaterial({ color: 0x009e60 }),
new THREE.MeshBasicMaterial({ color: 0x0051ba }),
new THREE.MeshBasicMaterial({ color: 0xffd500 }),
new THREE.MeshBasicMaterial({ color: 0xff5800 }),
new THREE.MeshBasicMaterial({ color: 0xC41E3A }),
new THREE.MeshBasicMaterial({ color: 0xffffff }),
];
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
for (let z = 0; z < 3; z++) {
const cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9);
const cube = new THREE.Mesh(cubeGeom, mats);
cube.castShadow = true;
cube.position.set(x * 3 - 3, y * 3 - 3 + 20, z * 3 - 3);
group.add(cube);
}
}
}
group.castShadow = true
scence.add(group);
/**
* 创建一个lambert材质的立方体
*/
const LambertMaterial = new THREE.MeshLambertMaterial({
color: 0x7777ff
});
const lambertSphere = new THREE.Mesh(sphereGeometry, LambertMaterial);
lambertSphere.castShadow = true;
lambertSphere.position.set(20, 20, 0);
scence.add(lambertSphere);
/**
* 创建一个Phong材质的立方体
*/
const PhongMaterial = new THREE.MeshPhongMaterial({
color: 0x7777ff
});
const PhongSphere = new THREE.Mesh(sphereGeometry, PhongMaterial);
PhongSphere.castShadow = true;
PhongSphere.position.set(40, 20, 0);
scence.add(PhongSphere);
/**
* 创建一个标准材质的立方体
*/
const Standardmaterial = new THREE.MeshStandardMaterial({ color: 0x7777ff });
const StandardCube = new THREE.Mesh(cubeGeometry, Standardmaterial);
StandardCube.castShadow = true;
StandardCube.position.set(60, 20, 0);
scence.add(StandardCube);
/**
* 创建一个物理材质的立方体
*/
const Physicalmaterial = new THREE.MeshPhysicalMaterial({ color: 0x7777ff });
const PhysicalCube = new THREE.Mesh(cubeGeometry, Physicalmaterial);
PhysicalCube.castShadow = true;
PhysicalCube.position.set(80, 20, 0);
scence.add(PhysicalCube);
/**
* 创建一个线材质的立方体
*/
const lineMater = new THREE.LineBasicMaterial({ vertexColors: true })
const geometry = new THREE.BufferGeometry()
const color = new THREE.Color();
let vertices = new Array();
let color1 = new Array();
for (let i = 0; i < 5000; i++) {
const x = Math.random() * 10
const y = Math.random() * 10
const z = Math.random() * 10
vertices.push(x, y, z);
color.setHSL(Math.random(), Math.random(), Math.random());
color1.push(color.r, color.g, color.b);
geometry.setAttribute(
'position',
new THREE.Float32BufferAttribute(vertices, 3)
);
geometry.setAttribute('color', new THREE.Float32BufferAttribute(color1, 3));
}
const mesh = new THREE.Line(geometry, lineMater)
mesh.position.set(100, 12.5, -5)
mesh.castShadow = true
scence.add(mesh)
}
效果如下: