Materials as assets and property type
Description: The current approach for materials requires materials to be defined per entity, without an easy way to re-use them. While mixins can be used to avoid the repetition in the HTML, it brings little to no runtime benefits. Instead, a material asset type could be introduced along with an accompanying property type. This would allow materials to be re-used and also passed to components.
Pseudo-code:
<a-assets>
<a-material id="wood" shader="phong" src="url(./wood.png)"></a-material>
<a-material id="red" shader="flat" color="red"></a-material>
</a-assets>
<a-box material="material: #wood"></a-box>
<a-entity hands-tracking-controls="hand: right; handMaterial: #red"></a-entity>
This would bring quite a few benefits as well as open the door to various possible optimizations:
- All defined materials and textures can be compiled/uploaded during the loading screen, minimizing stutters at runtime
- Memory usage can be reduced by re-using the same material instance
- When used throughout a scene, the sorting could take material ID in account (default behaviour in vanilla Three.js), reducing program switches
- Would potentially introduce a non-intrusive way to use BatchedMesh (#5396), as it requires the same material to be used
- Components can expose a single material property instead of individual properties for each tunable material property, allowing for greater flexibility (for example, changes like this would no longer be needed)
- Third party libraries could create materials on the fly that can be applied through common A-Frame approaches instead of Three.js, without having to register a shader for it.
To maintain backwards compatibility, the material component can still create materials on the fly, making it an opt-in feature for users to use. For components that would normally use a single color property and now a material property, it might be desirable to have a short-hand to also create "in-line" materials in properties, e.g.:
<a-entity hands-tracking-controls="hand: right; handMaterial: material(color: red)"></a-entity>
Alternatively a component can of-course continue to expose both the individual properties besides a material property.
Feedback and suggestions are welcome.
Hello it's a great idea. Do you think this could also work with a gltf?
Do you think this could also work with a gltf?
Yes, it should work with gltf. You can't directly use the material component on a gltf model, so you'd still need to write a component to apply the material or use a component like gltf-part. But these components could then accept a material as property type.
Ultimately I would like to make something like https://gltf.pmnd.rs/ so that you can have a gltf file and ahead-of-time split it into entities that behave like any other entity. Then it might even be possible to extract the materials from the gltf file, list them in <a-assets> allow you to tweak/adjust the materials and even apply them to other parts of the scene.