-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement clearcoat per the Filament and the KHR_materials_clearcoat
specifications.
#13031
Conversation
The generated |
You added a new feature but didn't update the readme. Please run |
specifications. Clearcoat is a separate material layer that represents a thin translucent layer of a material. Examples include (from the [Filament spec]) car paint, soda cans, and lacquered wood. This commit implements support for clearcoat following the Filament and Khronos specifications, marking the beginnings of support for multiple PBR layers in Bevy. The [`KHR_materials_clearcoat`] specification describes the clearcoat support in glTF. In Blender, applying a clearcoat to the Principled BSDF node causes the clearcoat settings to be exported via this extension. As of this commit, Bevy parses and reads the extension data when present in glTF. Note that the `gltf` crate has no support for `KHR_materials_clearcoat`; this patch therefore implements the JSON semantics manually. Clearcoat is integrated with `StandardMaterial`, but the code is behind a series of `#ifdef`s that only activate when clearcoat is present. Additionally, the `pbr_feature_layer_material_textures` Cargo feature must be active in order to enable support for clearcoat factor maps, clearcoat roughness maps, and clearcoat normal maps. This approach mirrors the same pattern used by the existing transmission feature and exists to avoid running out of texture bindings on platforms like WebGL and WebGPU. Note that constant clearcoat factors and roughness values *are* supported in the browser; only the relatively-less-common maps are disabled on those platforms. This patch refactors the lighting code in `StandardMaterial` significantly in order to better support multiple layers in a natural way. That code was due for a refactor in any case, so this is a nice improvement. A new demo, `clearcoat`, has been added. It's based on [the corresponding three.js demo], but all the assets are my original work. [Filament spec]: https://google.github.io/filament/Filament.html#materialsystem/clearcoatmodel [`KHR_materials_clearcoat`]: https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md [the corresponding three.js demo]: https://threejs.org/examples/webgl_materials_physical_clearcoat.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a first pass. the changes to the core lighting functions are pretty extensive, @mockersf could we please run a demo comparison?
i think we need to make proper efforts to stop the lighting code becoming more write-only than it already is. not saying this makes it much worse than it already was, but it's honestly very hard to follow.
it would also be nice to improve the example a bit (the three.js one is nicer, and i don't think their implementation is better) but that can certainly be done later.
|
||
impl ClearcoatExtension { | ||
#[allow(unused_variables)] | ||
fn parse( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this be upstreamed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a PR: gltf-rs/gltf#362
And it's been sitting since 2022. :( gltf
doesn't seem to be well maintained. I pinged the maintainer, but I don't think we can realistically block this PR on that...
#[cfg(feature = "pbr_multi_layer_material_textures")] | ||
{ | ||
if self.clearcoat_texture.is_some() { | ||
flags |= StandardMaterialFlags::CLEARCOAT_TEXTURE; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick - these flags should probably be added in the prepass as well in case anybody wants to use them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what this means. The prepass doesn't care about any of these flags, and we don't do this anywhere else (grepping for e.g. BASE_COLOR
brings up nothing related to prepasses, except for alpha discard, which isn't relevant here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I wouldn't add them. Sometime soon we should revisit how pipeline keys are managed however.
@robtfm I tried to improve the lighting code as I went and make it as easy to follow as possible. Sorry to hear that I didn't succeed :( Do you have any suggestions? |
i think the main issue i have is the specular aliasing from the normal maps. it seems less "bitty" in the 3js version. perhaps just downres the normal map, or just use a smaller one maybe so the single pixel highlights are less frequent?
yes sorry, i didn't mean to sound so critical. i think if you hadn't made such an effort it would be much worse, whereas now it's not much worse, and with more functionality. the 2 specific comments about a param struct and factoring the meshlet sample were the main things i thought would help. i guess if the lighting functions api is clean then at least the trickier stuff is more contained. |
@robtfm I believe every comment has been addressed. |
Mostly good, just a change in the transmission example: |
How do I get rid of the GitHub typos check on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good!
we should probably add something to the migration guide mentioning the changes required for custom prepasses/shaders that use apply_normal_mapping
.
I’ve read the discussion, has any GPU-profiling/benchmarking been done across vendors to see what impact the shader refactoring has on performance without clear coat? |
I did a quick test on my amd 6800xt, register pressure was identical and performance was the same according to radeon gpu profiler. |
No obvious performance differences for me testing vs main. What's blocking this moving forward? The more general changes seem like a marked improvement in standardization and code quality. |
@NthTensor It only has one approval. Having a second approval would be very helpful. |
Closing as I am burned out and have no motivation to get this landed anymore. |
@pcwalton once merge conflicts are resolved this should be good to merge. Do reach out if you'd like a hand with that. |
Updated. |
I'm comfortable with the thoroughness and expertise of the reviews here, and this isn't a controversial addition. Merging. |
Fixes a regression introduced by bevyengine#13031.
Fixes a regression introduced by #13031.
…ng_input.F_ab (#13379) # Objective - The clearcoat PR #13031 had a small typo which broke transmission - Fixes #13284 ## Solution - Set transmissive_lighting_input.F_ab to the correct value ![transmission_fix](https://github.com/bevyengine/bevy/assets/688816/92158117-de3a-4fa5-8af8-dcbd1d5eee04)
Clearcoat is a separate material layer that represents a thin translucent layer of a material. Examples include (from the Filament spec) car paint, soda cans, and lacquered wood. This commit implements support for clearcoat following the Filament and Khronos specifications, marking the beginnings of support for multiple PBR layers in Bevy.
The
KHR_materials_clearcoat
specification describes the clearcoat support in glTF. In Blender, applying a clearcoat to the Principled BSDF node causes the clearcoat settings to be exported via this extension. As of this commit, Bevy parses and reads the extension data when present in glTF. Note that thegltf
crate has no support forKHR_materials_clearcoat
; this patch therefore implements the JSON semantics manually.Clearcoat is integrated with
StandardMaterial
, but the code is behind a series of#ifdef
s that only activate when clearcoat is present. Additionally, thepbr_feature_layer_material_textures
Cargo feature must be active in order to enable support for clearcoat factor maps, clearcoat roughness maps, and clearcoat normal maps. This approach mirrors the same pattern used by the existing transmission feature and exists to avoid running out of texture bindings on platforms like WebGL and WebGPU. Note that constant clearcoat factors and roughness values are supported in the browser; only the relatively-less-common maps are disabled on those platforms.This patch refactors the lighting code in
StandardMaterial
significantly in order to better support multiple layers in a natural way. That code was due for a refactor in any case, so this is a nice improvement.A new demo,
clearcoat
, has been added. It's based on the corresponding three.js demo, but all the assets (aside from the skybox and environment map) are my original work.Changelog
Added
StandardMaterial
now supports a clearcoat layer, which represents a thin translucent layer over an underlying material.KHR_materials_clearcoat
extension, representing materials with clearcoat layers.Migration Guide
The lighting functions in the
pbr_lighting
WGSL module now have clearcoat parameters, ifSTANDARD_MATERIAL_CLEARCOAT
is defined.The
R
reflection vector parameter has been removed from some lighting functions, as it was unused.