- 作者:老汪软件技巧
- 发表时间:2024-11-17 04:01
- 浏览量:
EdgeSplitModifier 是 Three.js 中用于分割网格的边缘,以便对具有较大角度的相邻面进行处理,使它们拥有独立的法线,解决法线平滑和光照不自然的问题。这个修饰符常用于在模型中创建硬边效果,特别是在需要表现出锐利边缘的几何体(例如机械零件、建筑等)时。
EdgeSplitModifier 有一个方法
EdgeSplitModifier()
创建一个新的EdgeSplitModifier对象。
// 创建一个 IcosahedronGeometry 几何体
const geometry = new THREE.IcosahedronGeometry(10, 3);
// 创建一个 MeshPhongMaterial 材质
const material = new THREE.MeshPhongMaterial({ color: 0x00ff00, flatShading: true });
const mesh = new THREE.Mesh(geometry, material); // 使用修改后的几何体创建网格
mesh.castShadow = true;
mesh.receiveShadow = true;
// 将网格添加到场景中
scene.add(mesh);
// 从上方照射的白色平行光,强度为 0.5。
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(0, 50, 0);
directionalLight.castShadow = true;
scene.add( directionalLight );
// 添加环境光来补充场景的整体光照 使得反光物体能显示
const ambientLight = new THREE.AmbientLight(0x404040); // 环境光
scene.add(ambientLight);
方法
主要作用分割边缘:控制切割角度:法线处理:适用场景:观察效果:
在 3D 图形学中,硬边(Hard Edges)指的是一个几何体中相邻的两个面之间具有显著的角度差,从而形成一种明显的锐利边界效果。这种边界通常使几何体看起来更加棱角分明,而不是光滑连续的。在示例中 当 cutOffAngle 接近 180 时边角会滑些,为0时边角较明显
// 声明一些变量,包括材质、修改器、网格和基础几何体
let map, modifier, mesh, baseGeometry;
// 参数配置对象,控制是否应用平滑着色、边缘分割、切割角度等
const params = {
smoothShading: true, // 是否启用平滑着色
edgeSplit: true, // 是否启用边缘分割
cutOffAngle: 20, // 切割角度,单位为度
showMap: false, // 是否显示纹理贴图
tryKeepNormals: true, // 是否保留法线
};
// 添加环境光,提供基础的光照
scene.add( new THREE.HemisphereLight( 0xffffff, 0x444444, 3 ) );
// 使用 OBJLoader 加载一个 Cerberus 模型
new OBJLoader().load(
'https://raw.githubusercontent.com/mrdoob/three.js/refs/heads/master/examples/models/obj/cerberus/Cerberus.obj',
function ( group ) {
// 获取加载的模型的几何体
const cerberus = group.children[ 0 ];
const modelGeometry = cerberus.geometry;
// 初始化边缘分割修改器
modifier = new EdgeSplitModifier();
// 合并几何体的重复顶点(优化几何体)
baseGeometry = BufferGeometryUtils.mergeVertices( modelGeometry );
// 创建网格并设置初始材质
mesh = new THREE.Mesh( getGeometry(), new THREE.MeshStandardMaterial() );
// 根据平滑着色选项设置材质的 flatShading 属性
mesh.material.flatShading = ! params.smoothShading;
// 旋转模型,使其正确朝向
mesh.rotateY( - Math.PI / 2 );
// 设置模型的缩放和位移
mesh.scale.set( 3.5, 3.5, 3.5 );
mesh.translateZ( 1.5 );
// 将网格添加到场景中
scene.add( mesh );
// 如果设置了显示纹理,并且纹理已经加载,应用纹理到网格
if ( map !== undefined && params.showMap ) {

mesh.material.map = map;
mesh.material.needsUpdate = true;
}
// 执行渲染
render();
}
);
// 加载纹理贴图
new THREE.TextureLoader().load( 'https://raw.githubusercontent.com/mrdoob/three.js/refs/heads/master/examples/models/obj/cerberus/Cerberus_A.jpg', function ( texture ) {
// 加载纹理并设置颜色空间
map = texture;
map.colorSpace = THREE.SRGBColorSpace;
// 如果网格已经创建,并且需要显示纹理,更新网格的材质
if ( mesh !== undefined && params.showMap ) {
mesh.material.map = map;
mesh.material.needsUpdate = true;
}
});
// 更新网格的几何体和材质
function updateMesh() {
// 切换切割角度的值(0 或 180)
params.cutOffAngle = params.cutOffAngle == 0 ? 180 : 0;
// 如果网格存在,更新其几何体和材质
if ( mesh !== undefined ) {
// 获取新的几何体
mesh.geometry = getGeometry();
// 检查材质是否需要更新
let needsUpdate = mesh.material.flatShading === params.smoothShading;
// 根据平滑着色参数调整材质的 flatShading 属性
mesh.material.flatShading = params.smoothShading === false;
// 如果纹理存在,并且显示纹理的选项被启用,更新纹理
if ( map !== undefined ) {
needsUpdate = needsUpdate || mesh.material.map !== ( params.showMap ? map : null );
mesh.material.map = params.showMap ? map : null;
}
// 更新材质
mesh.material.needsUpdate = needsUpdate;
}
}
// 绑定 DOM 元素点击事件,点击时更新网格
DOMEl.onclick = () => {
updateMesh();
}
// 根据参数选择是否应用边缘分割,返回相应的几何体
function getGeometry() {
let geometry;
// 如果启用了边缘分割,应用 EdgeSplitModifier
if ( params.edgeSplit ) {
geometry = modifier.modify(
baseGeometry,
params.cutOffAngle * Math.PI / 180, // 将角度转为弧度
params.tryKeepNormals // 保留法线选项
);
} else {
geometry = baseGeometry; // 否则使用原始几何体
}
return geometry;
}