three 基础:材质
Material是材质的抽象基类。
- 构造属性
- 定义材质是否透明
transparent
:false ,开启后 opacity 有效 - 材质透明度
opacity
vertexColors
是否使用定点着色,默认 false。开启的时候记得把 color 属性给嘎了visible
材质是否可见,默认 false
- 定义材质是否透明
材质类型
- 网格材质 Mesh
- MeshBasicMaterial基础网格材质
- 光照无效
- MeshNormalMaterial 法线网格材质
- 光照无效
- 什么是法线?物体外侧的向量方向(关乎到关照,反射)
- 一般用于调试法线
- MeshMatcapMaterial
- 光照无效
- 根据法线选择正确的颜色
- 根据纹理图片渲染明暗,在没有光源的情况下,物体也会呈现出明暗面
matcap
设置纹理
- MeshDepthMaterial 深度网格材质
- 光照无效
- 深度基于相机远近平面。白色最近,黑色最远。
- MeshLambertMaterialLambert 网格材质
- 光照有效,漫反射,非光泽表面 的材质,没有镜面高光。
- 模拟地表(例如未经处理的木材或石材)
- MeshPhongMaterialPhong 网格材质
- 光照有效,镜面高光
- 高光颜色
specular
- 高亮程度 越高越亮
shininess
- MeshToonMaterial 卡通阴影效果的材质
- MeshStandardMaterial标准网格材质
- PBR 物理材质,模拟金属、玻璃,精准和逼真,计算成本高
- MeshPhysicalMaterial 物理网格材质
- MeshStandardMaterial 的扩展,提供了更高级的基于物理的渲染属性
- 外层有个透明样的图层
- MeshBasicMaterial基础网格材质
- PointsMaterial点材质
使用 MeshStandardMaterial 还原一个物体
添加金属度纹理
jsstandardMaterial.metalnessMap = matalnessTexture;
添加粗糙度纹理
jsstandardMaterial.roughnessMap = roughnessTexture;
添加颜色纹理
jsstandardMaterial.map = colorTexture;
添加环境遮挡纹理(需要第二组 uv)
jssphereMesh.geometry.setAttribute("uv2", new THREE.BufferAttribute(sphereMesh.geometry.attributes.uv.array, 2)); // 复制uv standardMaterial.aoMap = ambientOcclusionTexture; standardMaterial.aoMapIntensity = 1; // 强度
添加顶点位移纹理
jsstandardMaterial.displacementMap = heightTexture; // 位移纹理。需要足够多的顶点 standardMaterial.displacementScale = 0.05;
添加法线贴图纹理(更改颜色照亮的方式,只改变光照)
jsstandardMaterial.normalMap = normalTexture; standardMaterial.normalScale.set(0.5, 0.5);
添加不透明度纹理
jsstandardMaterial.transparent = true; standardMaterial.alphaMap = alphaTexture;
通过钩子修改材质
Material.onBeforeCompile
在编译着色器程序之前立即执行的可选回调。使用着色器源代码作为参数调用此函数。
材质的着色器一般位于node_modules/three/src/renderers/shaders
中。
修改顶点
将顶点着色器中的#include <begin_vertex>
替换掉。#include <begin_vertex>
原来的代码:
c#
export default /* glsl */`
vec3 transformed = vec3( position );
`;
添加静态 uniforms
js
material.onBeforeCompile = shader => {
shader.uniforms.uTime = {
value: 0,
};
shader.vertexShader = shader.vertexShader.replace(
"#include <common>",
`
#include <common>
float uTime;
`
);
};
添加动态 uniforms
可用defines
实现,但是,好掉帧 QAQ
js
// 塞点需要变的uniforms进去
material.defines = {
uTime: 0,
};
修复阴影
创建一个深度网格材质来作为自定义深度材质,同时将这个材质的着色器修改为和之前的材质相同。
js
const depthMaterial = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
});
// 修复阴影
depthMaterial.onBeforeCompile = shader => {
setCustomShader(shader);
// 改变顶点
shader.vertexShader = shader.vertexShader.replace(
"#include <begin_vertex>",
`
#include <begin_vertex>
float angle = (position.y + uTime) * 0.9; // 根据y坐标和时间,有着不同的旋转角度
mat2 rotateMatrix = getRotate2dMatrix(angle);
transformed.zx = transformed.zx * rotateMatrix; // 如果是xz的话就是顺时针转
`
);
};
mesh.customDepthMaterial = depthMaterial; // 使用自定义深度材质 用来修复阴影
修复法线(自身阴影面)
替换#include <beginnormal_vertex>
,修改法向量坐标objectNormal
和顶点的相同。
js
material.onBeforeCompile = shader => {
setCustomShader(shader);
// 修复法线
shader.vertexShader = shader.vertexShader.replace(
"#include <beginnormal_vertex>",
`
#include <beginnormal_vertex>
float angle = (position.y + uTime) * 0.9; // 根据y坐标和时间,有着不同的旋转角度
mat2 rotateMatrix = getRotate2dMatrix(angle);
objectNormal.zx = objectNormal.zx * rotateMatrix; // 如果是xz的话就是顺时针转
`
);
// 改变顶点
shader.vertexShader = shader.vertexShader.replace(
"#include <begin_vertex>",
`
#include <begin_vertex>
transformed.zx = transformed.zx * rotateMatrix; // 如果是xz的话就是顺时针转
`
);
};