bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Implement clearcoat per the Filament and the `KHR_materials_clearcoat` specifications.

Open pcwalton opened this issue 10 months ago • 12 comments

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 #ifdefs 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 (aside from the skybox and environment map) are my original work.

Screenshot 2024-04-19 101143

Screenshot 2024-04-19 102054

Changelog

Added

  • StandardMaterial now supports a clearcoat layer, which represents a thin translucent layer over an underlying material.
  • The glTF loader now supports the KHR_materials_clearcoat extension, representing materials with clearcoat layers.

Migration Guide

  • The lighting functions in the pbr_lighting WGSL module now have clearcoat parameters, if STANDARD_MATERIAL_CLEARCOAT is defined.

  • The R reflection vector parameter has been removed from some lighting functions, as it was unused.

pcwalton avatar Apr 19 '24 17:04 pcwalton

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

github-actions[bot] avatar Apr 19 '24 17:04 github-actions[bot]

You added a new feature but didn't update the readme. Please run cargo run -p build-templated-pages -- update features to update it, and commit the file change.

github-actions[bot] avatar Apr 19 '24 20:04 github-actions[bot]

@robtfm How would you like me to improve the example? I wanted to include a transparent one because @JMS55 asked me how clearcoat looked with transparency. Should I add more of a noise pattern to the car paint? Redo the golf ball texture?

pcwalton avatar Apr 22 '24 03:04 pcwalton

@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?

pcwalton avatar Apr 22 '24 03:04 pcwalton

@robtfm How would you like me to improve the example? I wanted to include a transparent one because @JMS55 asked me how clearcoat looked with transparency. Should I add more of a noise pattern to the car paint? Redo the golf ball texture?

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? the texture on the carpaint is nicer in 3js as well (and the spinning spheres) but i'm not sure that's worth adding a new texture for.

@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?

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 avatar Apr 22 '24 14:04 robtfm

@robtfm I believe every comment has been addressed. pbr_lighting.wgsl has been largely rewritten. I made the spheres rotate, added some blur and decreased the levels on the scratch normal map, added some subtle blue noise as a normal map to the car paint, and switched to ACES filmic tonemapping, as this is what makes the normal map on the car paint in three.js appear purple.

Screenshot 2024-04-22 160935

pcwalton avatar Apr 22 '24 23:04 pcwalton

just a first pass. the changes to the core lighting functions are pretty extensive, @mockersf could we please run a demo comparison?

Mostly good, just a change in the transmission example: https://pixel-eagle.vleue.com/project/B25A040A-A980-4602-B90C-D480AB84076D/run/852/compare/840?screenshot=3D%20Rendering/transmission.png

mockersf avatar Apr 22 '24 23:04 mockersf

How do I get rid of the GitHub typos check on Fo?

pcwalton avatar Apr 22 '24 23:04 pcwalton

add it to https://github.com/bevyengine/bevy/blob/main/typos.toml

mockersf avatar Apr 22 '24 23:04 mockersf

I think I fixed the transmission example, but it's hard for me to check locally as it's animated.

pcwalton avatar Apr 23 '24 02:04 pcwalton

the gold and golf balls looks great now, but the blue sphere doesn't show: ERROR bevy_asset::server: Path not found: [...]/assets/textures/BlueNoise-Normal.png

robtfm avatar Apr 23 '24 10:04 robtfm

@robtfm Oops, forgot to check that file in! Fixed.

pcwalton avatar Apr 23 '24 13:04 pcwalton

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?

superdump avatar May 01 '24 04:05 superdump

On NVIDIA, warp occupancy and register count are identical both before and after this PR.

Screenshot 2024-05-01 150843

Screenshot 2024-05-01 151432

pcwalton avatar May 01 '24 22:05 pcwalton

I did a quick test on my amd 6800xt, register pressure was identical and performance was the same according to radeon gpu profiler.

Elabajaba avatar May 01 '24 22:05 Elabajaba

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 avatar May 02 '24 12:05 NthTensor

@NthTensor It only has one approval. Having a second approval would be very helpful.

pcwalton avatar May 02 '24 19:05 pcwalton

Closing as I am burned out and have no motivation to get this landed anymore.

pcwalton avatar May 03 '24 07:05 pcwalton

@pcwalton once merge conflicts are resolved this should be good to merge. Do reach out if you'd like a hand with that.

alice-i-cecile avatar May 04 '24 14:05 alice-i-cecile

Updated.

pcwalton avatar May 05 '24 22:05 pcwalton

I'm comfortable with the thoroughness and expertise of the reviews here, and this isn't a controversial addition. Merging.

alice-i-cecile avatar May 05 '24 22:05 alice-i-cecile