Skip to content

Add more material examples#257

Merged
AdrienHerubel merged 16 commits intoAcademySoftwareFoundation:dev_1.1.1from
AntonPalmqvist:Add-more-material-examples
Sep 30, 2025
Merged

Add more material examples#257
AdrienHerubel merged 16 commits intoAcademySoftwareFoundation:dev_1.1.1from
AntonPalmqvist:Add-more-material-examples

Conversation

@AntonPalmqvist
Copy link
Copy Markdown
Contributor

Adding more example materials as requested in Slack-thread: https://academysoftwarefdn.slack.com/archives/C06365EAQMP/p1747159796578119?thread_ts=1747133441.958219&cid=C06365EAQMP

A couple questions:

Here's a selection of the materials, verified working in MaterialX Viewer:
imageimageimageimageimageimageimageimage

jstone-lucasfilm and others added 3 commits June 28, 2024 14:05
This changelist merges v1.1 development from dev_1.1 to main, in preparation for marking the release of OpenPBR v1.1.
- Bumped MaterialX version from 1.38 to 1.39 on existing examples
- Added new examples
@AdrienHerubel AdrienHerubel self-requested a review May 27, 2025 17:50
@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented May 31, 2025

Here is a first attempt at running all these materials in the Arnold testsuite.

They generally look good (to the extent that materials without textures can), but here are some minor suggestions:

  • The metals are all mirror-like, but would look more convincing if slightly rough IMO.
  • Were the F82 metal colors derived somehow from the metal n/k versus frequency data? If not, ideally they should be (we can write some script for that, e.g. using my script here to extract the spectral data).
  • The "velvet" fuzz material is grey, but probably looks more convincing if e.g. purple.
  • The difference between "lemon", "carrot", "banana" is just the base color.. Is that really helpful? At least maybe the roughness can vary, and add a partially present coat to simulate e.g. the waxiness of a lemon. (They don't really look like the actual fruits/veg anyway, due to no texturing..).
  • The fuzz lobe can also handle a dusty appearance when rough, so some "dusty" material would be good.
  • The base_diffuse_roughness appears to not be used in any case. This would probably be good to use in some cases (which are supposed to be rough diffuse), e.g. sand, brick.
  • Some dielectrics are rough (e.g. "salt", "ice"), but most are mirror smooth, why is that? Some slight roughness would be good in most cases.
  • "coffee" is done with subsurface. I think it would be better as transmission volume, since it is not very opaque.
  • "eye sclera" is rather pink for an eye?
  • "honey" is rather orange (e.g. compare this)
  • Only one emitter. How about an emitter under a coat, or under fuzz?
  • Is "petroleum" really that brown, I thought it would be more clear/yellow?
  • I think blood probably looks more opaque... though depends obviously on the scale of the ball.

palmqvist_arnold

@AntonPalmqvist
Copy link
Copy Markdown
Contributor Author

Thank you, these are great suggestions.

The purpose of the Physically Based database is to provide a reference to compare against, rather than to provide interesting looking surfaces. Let’s say for example you downloaded a lump of charcoal from an asset store and you suspect it’s not correctly color calibrated, that’s when you use the materials from Physically Based to validate against. That’s also why some of these materials may not be suitable as example materials.

I can remove the materials that don’t make sense as examples, where surface detail is expected, such as banana and lemon.

With that said, I’m open to adding procedural surface detail using MaterialX nodes, that don’t require any textures. For example, egg shell, car paint with metallic flakes, orange peel, etc. That’s a bigger task that would need some more time however.
I was looking into bringing over materials from this excellent resource https://github.com/stehrani3d/MaterialEggs/, but I couldn't open the scene with my Houdini Apprentice license.

  • The metals are all mirror-like, but would look more convincing if slightly rough IMO.
    • I’ve intentionally left out any surface texture and imperfections from the database, and these materials were brought over directly from the database without modifications, with a few exceptions like with Honey. The roughness values are only there to give a plausible default look, for example glass is expected to look smooth, and charcoal rough. With that said, I can make modifications just for these example materials.
  • Were the F82 metal colors derived somehow from the metal n/k versus frequency data? If not, ideally they should be (we can write some script for that, e.g. using my script here to extract the spectral data).
  • The "velvet" fuzz material is grey, but probably looks more convincing if e.g. purple.
    • I'll make sure to update that
  • The difference between "lemon", "carrot", "banana" is just the base color.. Is that really helpful? At least maybe the roughness can vary, and add a partially present coat to simulate e.g. the waxiness of a lemon. (They don't really look like the actual fruits/veg anyway, due to no texturing..).
    • As mentioned above, I'll probably remove these kinds of materials that doesn't make sense without surface texture
  • The fuzz lobe can also handle a dusty appearance when rough, so some "dusty" material would be good.
    • I'll make sure to update that
  • The base_diffuse_roughness appears to not be used in any case. This would probably be good to use in some cases (which are supposed to be rough diffuse), e.g. sand, brick.
    • I'll make sure to update that
  • Some dielectrics are rough (e.g. "salt", "ice"), but most are mirror smooth, why is that? Some slight roughness would be good in most cases.
    • As mentioned, the roughness values are only there to have good enough defaults
  • "coffee" is done with subsurface. I think it would be better as transmission volume, since it is not very opaque.
    • Good point, I'll look into it. I usually work in a real-time context and I tend to lean towards SSS whenever possible.
  • "eye sclera" is rather pink for an eye?
    • The "eye sclera" color was taken from this presentation http://www.iryoku.com/downloads/Next-Generation-Character-Rendering-v6.pptx Comparing to MetaHumans it’s quite close, but a little more on the red side as you say. It could be that they sampled the color by averaging surrounding areas and got more of the veins into that sample. It might indeed be wise to reduce the red a little. It should also have some amount of SSS.
  • "honey" is rather orange (e.g. compare this)
    • I'll make sure to update that
  • Only one emitter. How about an emitter under a coat, or under fuzz?
    • Good idea. I could probably also add a couple more, such as "digital display", "flourescent tube light", and a couple more color temperature variations of the "light bulb"
  • Is "petroleum" really that brown, I thought it would be more clear/yellow?
  • I think blood probably looks more opaque... though depends obviously on the scale of the ball.
    • You’re right, it should have strong absorption to make it look more opaque. I don’t have absorption values in the database because I haven’t been able to find any scientifical data on that yet, but I should at the very least try to visually match against a reference and use the values I end up with.

Thanks again for the suggestions and for testing this!

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 8, 2025

The purpose of the Physically Based database is to provide a reference to compare against, rather than to provide interesting looking surfaces. Let’s say for example you downloaded a lump of charcoal from an asset store and you suspect it’s not correctly color calibrated, that’s when you use the materials from Physically Based to validate against. That’s also why some of these materials may not be suitable as example materials.

It's good to attempt to provide reference values for known pure materials. In some cases, we should be able to look up (or derive) values close to a reference, e.g.:

  • IOR and Abbe number of dielectrics
  • colors of metals (derived from IOR/k tables, using calculations similar to Naty's)
  • Absorption properties of some liquids (possibly)

But in other cases I think the values vary too much in reality for there to be a meaningful reference (e.g. "coffee", "chocolate" -- what kinds?). Or, the appearance of the real material involves surface variations in texture/geometry, without which it looks unrealistic (e.g. the fruits, the skin, "car paint" -- with no flakes?). So I question really whether these can really be considered references. At the least though, they are useful starting points.

In the context of OpenPBR, I think they would mostly be useful as a suite of examples of the various effects that can be achieved with the model (assuming no surface variation). Which is useful for test suites, and for basic presets as starting points or for ideation. So for this OpenPBR set of materials, I would propose the goal should not be to try to provide reference examples, but to try to cover and (broadly) demonstrate the functionality of the model, in terms of the different kind of appearances it can generate. Which even without textures are reminiscent at least of various real materials (though in practice, without textures they look quite fake).

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 8, 2025

The metal colors were calculated using this script from Naty Hoffman:

https://github.com/natyh/material-params

It seems that his code there is calculating a fit specifically to the Gulbrandsen model. So we should modify this to instead fit to the metal model used in OpenPBR, which is a variant of Naty's F82 model (except the metal edge color in the model is expressed as a tint of the Schlick curve, so it is called the "F82-tint" model).

Probably @natyh has a code for fitting the F82 model somewhere, which would be easy to modify for F82-tint.

(The Adobe team, e.g. @peterkutz @virtualzavie @paule-adobe, wrote one too, used to derive metal edge tints for their ASM white paper, but I don't have access to their script).

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 8, 2025

I can remove the materials that don’t make sense as examples, where surface detail is expected, such as banana and lemon. With that said, I’m open to adding procedural surface detail using MaterialX nodes, that don’t require any textures. For example, egg shell, car paint with metallic flakes, orange peel, etc. That’s a bigger task that would need some more time however.

I would say, for OpenPBR at least, it's not necessary to try to add some procedural texturing. It would complicate the materials, and make them harder (or just impossible) to port outside of MaterialX. Also, even with such procedural texturing, it is still going to look rather "programmer art", and not close to a result from e.g. a scanned asset. It would be better IMO to have this suite be a very minimal set of examples with no surface variation, roughly covering the gamut of what is possible with the model (given no surface variation).

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 8, 2025

For petroleum, as with many other materials, there’s quite some variability. I based it roughly on this look: https://en.wikipedia.org/wiki/Petroleum#/media/File:Petroleum_sample.jpg

Ah, so crude oil.. I was confused and thought it meant petrol (the British word for gasoline), which is much clearer (on the scale of a jar of the stuff).

@portsmouth
Copy link
Copy Markdown
Contributor

I think blood probably looks more opaque... though depends obviously on the scale of the ball.

You’re right, it should have strong absorption to make it look more opaque. I don’t have absorption values in the database because I haven’t been able to find any scientifical data on that yet, but I should at the very least try to visually match against a reference and use the values I end up with.

Note that for the volumetric materials (e.g. blood, skin, coffee, etc.) to be correct for the scale of the ball, the units of the subsurface_radius and transmission_depth need to set to cm.

Since according to:

https://github.com/usd-wg/assets/tree/main/full_assets/StandardShaderBall

"The scene adopts the convention of one scene unit equals 1cm. There is layer metadata to indicate this (metersPerUnit = 0.01).

  • Sphere: Ø7.53cm diameter, 9.83mm thickness.
  • Rim: Ø8.92cm diameter, 6.25mm thickness.
  • Floor: 100cm×100cm, tile size 4cm×4cm."

So it's a sort of grapefruit sized thing.. Anyway, as long as the length units are set in cm (given the MFP you assume, in whatever units), it should look correct for this (grapefruit sized) ball.

image

@portsmouth
Copy link
Copy Markdown
Contributor

What color space are you assuming for your RGB values, by the way? In my Arnold renders, I took them to be ACEScg colors, but perhaps they were intended to be sRGB?

@AntonPalmqvist
Copy link
Copy Markdown
Contributor Author

What color space are you assuming for your RGB values, by the way? In my Arnold renders, I took them to be ACEScg colors, but perhaps they were intended to be sRGB?

They're all sRGB.

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 9, 2025

They're all sRGB.

OK, I need to re-do my renders. (The colorspace is even specified in the files, colorspace="lin_rec709", doh..).

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 9, 2025

we should modify this to instead fit to the metal model used in OpenPBR, which is a variant of Naty's F82 model (except the metal edge color in the model is expressed as a tint of the Schlick curve, so it is called the "F82-tint" model).

I had a go at modifying (and simplifying) @natyh's code to compute the F82-tint color (from the metal data at refractiveindex.info:

https://github.com/portsmouth/F82-tint-generator

image

(Some metals don't have enough data in the visible range of wavelengths, but the ones I tabulated all do). This produces results roughly similar to the ASM values:

image

But clearly not a great match. Also some of the F0 colors look a bit suspect, e.g.: Tungsten comes out pinkish, but wikipedia says it is "a greyish-white lustrous metal". And Titanium F0 is much brighter than ASM's (though their darker value seems less likely to be correct, since titanium metal is fairly silvery).

Note that the F82-tint color will generally be less saturated and brighter than the corresponding Gulbrandsen edge color (or the original F82), since it is just the tint of Schlick (at 82 degrees) which already has some F0 color.

Possibly my color calculations are not fully correct (I will check, or if anyone spots an error, let me know). I just did:

    # Integrate Fresnel over CMFs to get XYZ color (for given angle)
    if colorspace=="ACEScg":   illuminant = colour.SDS_ILLUMINANTS["D60"]
    elif colorspace=="sRGB":   illuminant = colour.SDS_ILLUMINANTS["D65"]
    XYZ_F0  = colour.sd_to_XYZ(F0_spectral,  cmfs=cmfs, illuminant=illuminant) / 100
    XYZ_F82 = colour.sd_to_XYZ(F82_spectral, cmfs=cmfs, illuminant=illuminant) / 100

    # Convert to (linear) RGB
    RGB_F0  = colour.XYZ_to_RGB(XYZ_F0,  RGB_COLOURSPACES[colorspace])
    RGB_F82 = colour.XYZ_to_RGB(XYZ_F82, RGB_COLOURSPACES[colorspace])

But Naty does some slightly more complicated thing requiring "chromatic adaptation since D60 and AP1 have slightly different white points". Although the API of colour seems to apply that the above calculation should account for this.

(If we can compare with the ASM script, it would be very helpful. cc @peterkutz @paule-adobe).

(NB, I tried adding Naty's modifications to do with chromatic adaptation, but it made no difference to the results (at 3-digit accuracy anyway)).

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 10, 2025

Re-rendering in sRGB I get this. The colors are less saturated/harsh now (which makes sense, since assuming the shader RGB values were ACEScg which has a wider gamut, would generate stronger colors).

anton_sRGB

@portsmouth
Copy link
Copy Markdown
Contributor

portsmouth commented Jun 10, 2025

I went through the IOR data and tried to use what seemed like the most reliable dataset in each case (from refractiveindex.info). I also added some more exotic metals to the list. These results seem closer to the ASM ones now (e.g. Titanium is similarly dark now).

I think it would be good to include this table in the spec (ported to Markdown, so the values can be copy-pasted, and also maybe with a shaderball render per metal).

output

@AdrienHerubel AdrienHerubel marked this pull request as draft June 10, 2025 15:13
@AdrienHerubel
Copy link
Copy Markdown
Contributor

Converting back to draft to address reviewer comments.

- Updated all colors to ACEScg
- All metals now have F82 as specular_color
- Added a few more metals from Portsmouth's chart
- Added SSS to Sclera and made it less red
- Added LCD Display material
- Added two variations of Light Bulb with different CCT
- Added base_diffuse_roughness to Brick, Charcoal, and Sand
- Made Velvet purple so it's more convincing
@AntonPalmqvist
Copy link
Copy Markdown
Contributor Author

Updated the Blood material with a transmission_depth value of 0.08 so it matches my reference image better.

Question: Could the Absorption Coefficient value from RefractiveIndex be used somehow with, or maybe even without, conversion?

image
Reference image of blood

image

@AntonPalmqvist
Copy link
Copy Markdown
Contributor Author

Improved coffee material with updated Transmission Color and Transmission Depth values. I also assigned the same dispersion value as water since it consists mostly of water, but not entirely sure if it's correct to assume they're the same.

image image
Reference images of coffee

image image image image image

@AntonPalmqvist
Copy link
Copy Markdown
Contributor Author

AntonPalmqvist commented Aug 5, 2025

Split the Honey material into two, liquid and crystallized, as they're quite different but both are also very common.

The difference can be best described as:
"Fresh honey is liquid and clear but with time it crystallizes and becomes thicker and less clear. The crystallization depends on temperature and the ratio of glucose and fructose."

image image
Reference images of honey

image image image image

@AntonPalmqvist AntonPalmqvist marked this pull request as ready for review August 10, 2025 23:41
@AdrienHerubel AdrienHerubel changed the base branch from main to dev_1.1.1 September 30, 2025 15:39
Copy link
Copy Markdown
Contributor

@AdrienHerubel AdrienHerubel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in scope for the 1.1.1 fix release, let's address merge conflicts.

Signed-off-by: Adrien Herubel <AdrienHerubel@users.noreply.github.com>
@AdrienHerubel AdrienHerubel self-requested a review September 30, 2025 15:44
Copy link
Copy Markdown
Contributor

@AdrienHerubel AdrienHerubel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed it in the regular meeting and there was a consensus that these presets could provide a good base for presets and implementers.

@AdrienHerubel AdrienHerubel merged commit 2696fe5 into AcademySoftwareFoundation:dev_1.1.1 Sep 30, 2025
1 check passed
@AntonPalmqvist AntonPalmqvist deleted the Add-more-material-examples branch September 30, 2025 16:19
AdrienHerubel added a commit that referenced this pull request Mar 3, 2026
* Update OpenPBR default example (#216)

This changelist updates the OpenPBR default example, matching its values to the latest default values of the shading model.

* Change thin film IOR default (#211)

From 1.5 to 1.4.  

As this won't make much difference to the look in implementations that ignore the adjacent IORs of the film.

But for those that take it into account, this will make the film visible rather than invisible by default (since `specular_ior` is 1.5 by default, and `coat_ior` 1.6).

* Add note about dark fuzz (#207)

Addressing #176

* Enable Zeltner sheen (#217)

This changelist enables Zeltner sheen in the reference implementation of OpenPBR, leveraging the new functionality in MaterialX 1.39.

Additionally, the open_pbr_velvet.mtlx example has been updated to account for the visual differences between Conty-Kulla and Zeltner sheen.

* Add a "resources" section to the front page (#215)

With links to
  - MaterialX web viewer running OpenPBR default material
  - OpenPBR-viewer project and web app

* Clarify formula for emission color (#209)

Following the discussion of #85.

* Update subsurface color types (#220)

This changelist updates the types associated with physical color values for subsurface scattering in OpenPBR, aligning with the conclusions of recent threads on ASWF Slack channels.

- Change `subsurface_radius_scale` from a `vector3` to a `color3` in the specification, aligning with the MaterialX implementation of OpenPBR.
- Change the `radius` input of `subsurface_bsdf` from a `vector3` to a `color3` in the MaterialX implementation, aligning with the current definition of the `subsurface_bsdf` node in MaterialX 1.39.

* Update specification and reference to v1.1 (#221)

* Add "Flexibility of implementation" section (#248)

* Add page to propose real-time approximations

* Mention layering and mixing approximation

* Mantion specular reflection approximation

* Mention anisotropic reflection approximations

* Fix typos

* Wording

* Reword the section, move it to the main document, remove the annex

* Subsurface in thin-walled mode, small clarification (#258)

* Merge v1.1 development to main (#222)

This changelist merges v1.1 development from dev_1.1 to main, in preparation for marking the release of OpenPBR v1.1.

* Subsurface in thin-walled mode, small clarification

* Subsurface in thin-walled mode, small clarification

---------

Co-authored-by: Jonathan Stone <jstone@lucasfilm.com>

* Allow emission_color components to exceed 1 (#260)

* Add more material examples (#257)

* Merge v1.1 development to main (#222)

This changelist merges v1.1 development from dev_1.1 to main, in preparation for marking the release of OpenPBR v1.1.

* Adding more material examples
- Bumped MaterialX version from 1.38 to 1.39 on existing examples
- Added new examples

* - Added MIT Black

* Color updates:
- Updated all colors to ACEScg
- All metals now have F82 as specular_color
- Added a few more metals from Portsmouth's chart

* Material updates:
- Added SSS to Sclera and made it less red
- Added LCD Display material
- Added two variations of Light Bulb with different CCT

* Material updates:
- Added base_diffuse_roughness to Brick, Charcoal, and Sand
- Made Velvet purple so it's more convincing

* Updated roughness values

* Removed a few materials that were less useful as examples

* Renamed Polyurethane

* Updated Blood material

* Added Abbe value to Blood material

* Updated IOR of Blood

* - Updated coffee material

* Split Honey into two materials, liquid and crystallized

* - Updated Honey (Crystallized) roughness value

---------

Signed-off-by: Adrien Herubel <AdrienHerubel@users.noreply.github.com>
Co-authored-by: Jonathan Stone <jstone@lucasfilm.com>
Co-authored-by: Adrien Herubel <AdrienHerubel@users.noreply.github.com>

* Integrate OpenPBR update from MaterialX project (#265)

* Integrate OpenPBR updates from MaterialX project

This changelist integrates two post-1.1 updates to OpenPBR Surface from the MaterialX project:

- Optimizations to OpenPBR graph (AcademySoftwareFoundation/MaterialX#2459)
- Add code generation hints support (AcademySoftwareFoundation/MaterialX#1954)

The more substantial update is the graph optimization, and I've copied the performance measurements from the original change for reference:

Performance tests were conducted on an NVIDIA RTX A6000 at 4K resolution, and the following timing improvements were seen:

OpenPBR Carpaint: 16ms -> 7ms
OpenPBR Glass: 27ms -> 11ms
OpenPBR Pearl: 16ms -> 12ms
OpenPBR Aluminum: 14ms -> 5ms

* Omit hardware shading optimizations

* Move anisotropy figure before Multiple Scattering section

* Revert CHANGELOG.md to upstream/dev_1.2 (belongs in separate PR #295)

---------

Signed-off-by: Adrien Herubel <AdrienHerubel@users.noreply.github.com>
Co-authored-by: Jonathan Stone <jstone@lucasfilm.com>
Co-authored-by: Julien Guertault <9511025+virtualzavie@users.noreply.github.com>
Co-authored-by: Anton Palmqvist <13031779+AntonPalmqvist@users.noreply.github.com>
Co-authored-by: Adrien Herubel <AdrienHerubel@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants