问题
The AFrame performance docs (https://github.com/aframevr/aframe/blob/master/docs/introduction/best-practices.md) recommend pre-baked lighting. I have done this, so now I'd like my mesh to use flat shading. However I'm unclear how to do this?
<a-gltf-model src="..." material="shader: flat">
This has no effect. I also tried iterating the nodes in three.js and setting each material to flat, but that didn't work either. Complete code trying a bunch of things:
<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>
This renders like this:
The mesh (on the left) has shading, whereas the box (on the right) is flat shaded. How can I set my mesh to use flat shading?
回答1:
Based on clues from @WestLangley, this code works:
<!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>
回答2:
OP mistakenly referred to unlit shading as flat shading. The later is usually a reference to non-interpolated normal shading. I've kept the original answer below, because it can still be useful for future reference.
Updated Answer:
MeshBasicMaterial
can be used to render unlit faces.
Original Answer:
I don't know for sure if there's a way of modifying this on aframe instantiation, but on the three.js side you can update material shading like the following:
node.material.flatShading = true;
node.material.needsUpdate = true;
This JSFiddle illustrates this.
回答3:
I used the answers here to put together an a-frame component that sets an a-entity as unlit, including with meshes that have child meshes
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]);
}
});
}
});
All you need to do then is add unlit as a component, like so
<a-entity unlit gltf-model="#model">
来源:https://stackoverflow.com/questions/56299870/aframe-how-to-use-flat-shading-on-a-mesh