AFrame:如何在网格上使用平面着色
AFrame: how to use flat shading on a mesh
AFrame 性能文档 (https://github.com/aframevr/aframe/blob/master/docs/introduction/best-practices.md) 推荐预烘焙光照。我已经这样做了,所以现在我希望我的网格使用平面着色。但是我不清楚该怎么做?
<a-gltf-model src="..." material="shader: flat">
这没有效果。我还尝试迭代 three.js 中的节点并将每个 material 设置为平坦,但这也不起作用。尝试一堆东西的完整代码:
<html>
<head>
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #000000">
<!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
<a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
<a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
</a-scene>
<script>
var office = document.getElementById( 'gltf' );
office.addEventListener( 'object3dset', () => {
const mesh = office.getObject3D( 'mesh' );
mesh.children[0].material.flatShading = true;
mesh.children[0].material.needsUpdate = true;
mesh.children[0].geometry.normalsNeedUpdate = true;
mesh.traverse( node => {
if ( node.isMesh === undefined || node.isMesh === false ) {
return;
}
node.material.flatShading = true;
node.material.needsUpdate = true;
node.geometry.normalsNeedUpdate = true;
} );
} );
</script>
</body>
</html>
呈现如下:
网格(左侧)有阴影,而框(右侧)是平面阴影。如何设置网格以使用平面着色?
OP 错误地将 无光照着色 称为 平面着色。后者通常是对 non-interpolated 法线着色的引用。我保留了下面的原始答案,因为它仍然可以供将来参考。
更新答案:
MeshBasicMaterial
可用于渲染未点亮的面。
原答案:
我不确定是否有办法在 aframe 实例化上修改它,但在 three.js 方面,您可以更新 material 阴影,如下所示:
node.material.flatShading = true;
node.material.needsUpdate = true;
这个JSFiddle说明了这一点。
根据@WestLangley 提供的线索,此代码有效:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #000000">
<!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
<a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
<a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
</a-scene>
<script>
var office = document.getElementById( 'gltf' );
office.addEventListener( 'object3dset', () => {
const mesh = office.getObject3D( 'mesh' );
mesh.children[0].material = new THREE.MeshBasicMaterial({map: mesh.children[0].material.map});
} );
</script>
</body>
</html>
我使用此处的答案组合了一个 a-frame 组件,该组件将 a-entity 设置为不发光,包括具有子网格的网格
AFRAME.registerComponent('unlit', {
init: function () {
function recursivelySetChildrenUnlit(mesh) {
if (mesh.material && mesh.material.map) {
mesh.material = new THREE.MeshBasicMaterial({ map: mesh.material.map });
}
if (mesh.children) {
for (var i = 0; i < mesh.children.length; i++) {
recursivelySetChildrenUnlit(mesh.children[i]);
}
}
}
this.el.addEventListener('model-loaded', (e) => {
const mesh = e.target.getObject3D('mesh');
for (var i = 0; i < mesh.children.length; i++) {
recursivelySetChildrenUnlit(mesh.children[i]);
}
});
}
});
然后您需要做的就是将 unlit 添加为一个组件,就像这样
<a-entity unlit gltf-model="#model">
AFrame 性能文档 (https://github.com/aframevr/aframe/blob/master/docs/introduction/best-practices.md) 推荐预烘焙光照。我已经这样做了,所以现在我希望我的网格使用平面着色。但是我不清楚该怎么做?
<a-gltf-model src="..." material="shader: flat">
这没有效果。我还尝试迭代 three.js 中的节点并将每个 material 设置为平坦,但这也不起作用。尝试一堆东西的完整代码:
<html>
<head>
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #000000">
<!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
<a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
<a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
</a-scene>
<script>
var office = document.getElementById( 'gltf' );
office.addEventListener( 'object3dset', () => {
const mesh = office.getObject3D( 'mesh' );
mesh.children[0].material.flatShading = true;
mesh.children[0].material.needsUpdate = true;
mesh.children[0].geometry.normalsNeedUpdate = true;
mesh.traverse( node => {
if ( node.isMesh === undefined || node.isMesh === false ) {
return;
}
node.material.flatShading = true;
node.material.needsUpdate = true;
node.geometry.normalsNeedUpdate = true;
} );
} );
</script>
</body>
</html>
呈现如下:
网格(左侧)有阴影,而框(右侧)是平面阴影。如何设置网格以使用平面着色?
OP 错误地将 无光照着色 称为 平面着色。后者通常是对 non-interpolated 法线着色的引用。我保留了下面的原始答案,因为它仍然可以供将来参考。
更新答案:
MeshBasicMaterial
可用于渲染未点亮的面。
原答案:
我不确定是否有办法在 aframe 实例化上修改它,但在 three.js 方面,您可以更新 material 阴影,如下所示:
node.material.flatShading = true;
node.material.needsUpdate = true;
这个JSFiddle说明了这一点。
根据@WestLangley 提供的线索,此代码有效:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #000000">
<!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
<a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
<a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
</a-scene>
<script>
var office = document.getElementById( 'gltf' );
office.addEventListener( 'object3dset', () => {
const mesh = office.getObject3D( 'mesh' );
mesh.children[0].material = new THREE.MeshBasicMaterial({map: mesh.children[0].material.map});
} );
</script>
</body>
</html>
我使用此处的答案组合了一个 a-frame 组件,该组件将 a-entity 设置为不发光,包括具有子网格的网格
AFRAME.registerComponent('unlit', {
init: function () {
function recursivelySetChildrenUnlit(mesh) {
if (mesh.material && mesh.material.map) {
mesh.material = new THREE.MeshBasicMaterial({ map: mesh.material.map });
}
if (mesh.children) {
for (var i = 0; i < mesh.children.length; i++) {
recursivelySetChildrenUnlit(mesh.children[i]);
}
}
}
this.el.addEventListener('model-loaded', (e) => {
const mesh = e.target.getObject3D('mesh');
for (var i = 0; i < mesh.children.length; i++) {
recursivelySetChildrenUnlit(mesh.children[i]);
}
});
}
});
然后您需要做的就是将 unlit 添加为一个组件,就像这样
<a-entity unlit gltf-model="#model">