Notes on adding a bevy_pbr_types crate
#18875
greeble-dev
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
These notes document my attempt at moving parts of
bevy_pbrinto a newbevy_pbr_typescrate.Why?
I want to make
bevy_gltfless dependent on render crates likebevy_pbr. This would be good for compile times and other things - see my previous notes for more info.A secondary goal is to document options for the render crate restructure. I feel that working through one narrow case in full can surface useful information, and solving problems for one crate can benefit other crates.
Also, I just really like refactoring things. This is a normal hobby enjoyed by normal people such as myself.
How?
bevy_gltfmostly wants to construct component and asset data defined inbevy_pbr- it doesn't need 95% of the code. So I moved these components and assets into a newbevy_pbr_typescrate - thenbevy_gltfdepends only on this crate and notbevy_pbr.StandardMaterial
The biggest hurdle is
StandardMaterial.bevy_gltfjust wants to construct it as an asset, but the same struct also does bind group layout. This is required by theMaterialtrait, which is bound onAsset + AsBindGroup.We don't want to pull all the bind group stuff into
bevy_pbr_types- instead we wantStandardMaterialto be just anAssetand let something else do the rest.First, I changed
Materialto remove theAssetbound. Instead it links to an asset type, and requires afrom_source_assetmethod to construct itself from that asset:This means
MeshMaterial3dcan point to anAssetinstead of aMaterial:Now any
Assettype can be a material, and it's up to the renderer internals to say how that type gets turned into aMaterial.But at this point we haven't achieved much since
StandardMaterialstill implements bothAssetandMaterial.Next I made a duplicate of
StandardMaterialcalledStandardMaterialInternal(which is obviously bad, but I'll get to that later).StandardMaterialis anAsset.StandardMaterialInternalis aMaterial+ bind group layout, and gets afrom_source_assetimplementation that takesStandardMaterial:Once that's all done,
StandardMaterialandMeshMaterial3dcan move tobevy_pbr_types.Problems
Duplicating the whole of
StandardMaterialis a big oof. There's also some boilerplate elsewhere - various custom materials still implement bothAssetandMaterial, but need this faff to link them together:impl Material for CustomMaterial { + type SourceAsset = Self; + + fn from_source_asset(source_asset: Self::SourceAsset) -> Self { + source_asset + }In practice the only thing that calls
from_source_assetisPreparedMaterial::prepare_asset, which immediately turns the struct into uniforms and bind groups and then throws it away. If that work can be done without the intermediate struct then a lot of the duplication and boilerplate can disappear.Another issue is that users might be confused by
MeshMaterial3d<M: Asset>, since there's no indication of what types are actually compatible. One solution might be to add an emptyMaterialAssettrait just to make the dependency clear, but that means yet more boilerplate for material implementors.Light Components
bevy_gltfwants to constructPointLight,DirectionalLightandSpotLightcomponents. These are fairly plain data, except they're tied to renderer internals by required components and hooks.The required components can move to
PbrPlugin::build, although it's a bit ugly:In theory the
on_addhook can also movePbrPlugin::build:But I couldn't get that working. It seems to register fine but never triggers.
register_component_hooks_by_idalso didn't work as the id couldn't be found. So for now I've left theon_addhook on the component.The Rest
Various types and consts also moved to
bevy_pbr_types, becausebevy_gltfuses them directly or they're used byStandardMaterialor the light components. These were all simple cut and pastes.And We're Done?
Full branch is here: main...greeble-dev:bevy:gltf-pbr-types
So Was It All Worth It?
Maybe. The immediate goal is achieved, although there's only a slight improvement in build times since it hasn't reduced the critical path by much.
The main issue is whether the material changes are a good idea. Adding all that faff and boilerplate is bad if the only goal is reducing
bevy_gltfdependencies. But maybe they end up aligning with other efforts to refactor materials and make them more data-driven.What's Next?
bevy_pbr_typesandbevy_gltfare still dependent onbevy_render. This could be solved by creatingbevy_render_types, but I don't currently have any plans to pull that thread.Beta Was this translation helpful? Give feedback.
All reactions