Skip to content
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

Nodes: MaterialX Noise Functions Lib #24504

Merged
merged 7 commits into from
Aug 17, 2022

Conversation

sunag
Copy link
Collaborator

@sunag sunag commented Aug 16, 2022

Related issue: #20541

Description

This is an early part of the implementation.

NodeMaterial

ShaderNode

  • add fn method to create function using backend shader language. commit

Example

  • add webgl_nodes_materialx_noise commit

https://raw.githack.com/sunag/three.js/dev-materialx-functions-lib/examples/webgl_nodes_materialx_noise.html

image

This contribution is funded by Google via Igalia

@sunag sunag marked this pull request as ready for review August 16, 2022 17:36
@sunag sunag added this to the r144 milestone Aug 16, 2022
@mrdoob
Copy link
Owner

mrdoob commented Aug 17, 2022

This is looking great!

@mrdoob mrdoob merged commit 0fd7bb6 into mrdoob:dev Aug 17, 2022
@mrdoob
Copy link
Owner

mrdoob commented Aug 17, 2022

Thanks!

@mrdoob
Copy link
Owner

mrdoob commented Aug 17, 2022

/fyi @jstone-lucasfilm

@jstone-lucasfilm
Copy link

This looks really promising, thanks @sunag and @mrdoob.

Over time, I wonder if we might be able to increase the degree of code sharing between the MaterialX and three.js codebases, so that future refinements to core shading code (e.g. noise functions such as mx_worley_noise_vec3) can be made in a central location and inherited by the other project when needed.

Based on work that was started at Autodesk, we have early JavaScript bindings for MaterialX libraries such as MaterialXGenGlsl, so one option would be to determine what's missing from those bindings that would be needed for three.js to call into this library directly, generating the required GLSL code when a MaterialX node (e.g. worleynoise3d) is referenced in an asset.

None of these considerations should block the great work that I'm seeing in progress, but it seems worthwhile to consider them for the future.

@mrdoob
Copy link
Owner

mrdoob commented Aug 17, 2022

Thanks for the pointers!

Over time, I wonder if we might be able to increase the degree of code sharing between the MaterialX and three.js codebases, so that future refinements to core shading code (e.g. noise functions such as mx_worley_noise_vec3) can be made in a central location and inherited by the other project when needed.

That would be great indeed! Maybe a npm package with all the snippets?

@jstone-lucasfilm
Copy link

@mrdoob That's a really good suggestion. We currently package MaterialX-generated shader snippets for OSL in this way, allowing them to be individually accessed in tools that perform their own final shader generation. It should be straightforward to extend this to GLSL in the future, and the results could indeed be shared directly through npm and other package managers.

For the formatting of this shader snippet library, would it be reasonable to have a separate GLSL file for each MaterialX node, including the definition of that node plus file references to any shared GLSL libraries upon which it depends? That's the pattern we currently use for OSL, so it would likely be the most straightforward starting point for GLSL and other languages.

@mrdoob
Copy link
Owner

mrdoob commented Aug 17, 2022

@sunag what do you think?

@sunag
Copy link
Collaborator Author

sunag commented Aug 18, 2022

Thanksss @jstone-lucasfilm :) . Soon after reading the comment I thought of making a live example using MaterialX, and it worked perfectly with the GLSL code already in the MaterialX repository.

Live
https://raw.githack.com/sunag/three.js/dev-materialx-live/examples/webgl_nodes_materialx_live.html

Code

import { MeshPhysicalNodeMaterial, code, fn } from 'three-nodes/Nodes.js';

const mxNoiseURL = "https://raw.githubusercontent.com/AcademySoftwareFoundation/MaterialX/main/libraries/stdlib/genglsl/lib/mx_noise.glsl";
const mxNoiseLive = await fetch( mxNoiseURL );
const mxNoise = code( await mxNoiseLive.text() );

const mxIncludes = [ mxNoise ];

const mx_perlin_noise_float = fn( 'float mx_perlin_noise_float( vec3 p )', mxIncludes );

//..

const material = new MeshPhysicalNodeMaterial();
material.colorNode = mx_perlin_noise_float( someCoordNode );

Using interfaces to identify the signature of the functions we can refine the code at will, including the dependencies.

In a way this is already possible without much effort, of course we can do something more organized creating a npm package if needed or create only one build in the MaterialX repo itself for this purpose, but I think the idea of @jstone-lucasfilm is very good.

@donmccurdy
Copy link
Collaborator

donmccurdy commented Aug 24, 2022

For the formatting of this shader snippet library, would it be reasonable to have a separate GLSL file for each MaterialX node, including the definition of that node plus file references to any shared GLSL libraries upon which it depends? ...

In the npm ecosystem, the path an end-user imports is abtracted from the files on disk. Separate files for each node would be completely fine, there just needs to be something (usually a src/index.js entry) that defines a list of all entrypoints to the module:

// index.js
export * from './nodes/a.js';
export * from './nodes/b.js';
export * from './nodes/c.js';
// ...

Those files may in turn import from any shared GLSL libraries they require. The end-user only sees something like this:

import { b } from '@materialx/glsl';

Happy to help with the scaffolding if MaterialX wants to go in that direction!

@sunag
Copy link
Collaborator Author

sunag commented Aug 24, 2022

@donmccurdy I made a draft here a few days ago but I think about doing a PR after the name of the nodes becomes more mature in the context of three.js. Anyway, I also think that would be the better way too.

@sunag
Copy link
Collaborator Author

sunag commented Sep 9, 2022

@jstone-lucasfilm have you ever thought of putting an attribute of canvas position XY in mtlx this is just for the purpose of editing in a node editor?

For example:

<texcoord name="texcoord1" type="vector2" posx="100" posy="50" />

This would represent a node in the editor at position { x:100, y:50 }. I think it would allow exporting not only the material but the entire editing canvas, so it can be used in other node editors with the same arrangement.

@jstone-lucasfilm
Copy link

@sunag Although they're not yet leveraged in production tools, there are actually xpos and ypos attributes in MaterialX that address this use case:

https://materialx.org/assets/MaterialX.v1.38.Spec.pdf#page=42

We're planning to support this feature in the upcoming Open MaterialX Graph Editor, which is scheduled to appear on GitHub later this year:

https://materialx.org/assets/ASWF_OSD2022_MaterialX_OSL_Final.pdf#page=26

One caveat is that the xpos and ypos attributes are expressed as multiples of the default width and height of a node in the application, rather than being literal pixel positions. Our thinking is that this makes them more transferrable between applications with radically different node layouts, though we're open to new ideas from the community on improving this convention.

@sunag
Copy link
Collaborator Author

sunag commented Sep 9, 2022

Ohh... Amazing!! Certainly Open MaterialX Graph Editor and Three.js Node Editor will have a great exchange soon.

@mrdoob
Copy link
Owner

mrdoob commented Sep 9, 2022

@jstone-lucasfilm Any plans on generating wgsl files too? https://www.w3.org/TR/WGSL/

@jstone-lucasfilm
Copy link

@mrdoob Not yet, though if there's a good case to be made for direct generation of WGSL, I believe that would be a straightforward feature to add. What are your thoughts on the benefits this would bring?

@sunag
Copy link
Collaborator Author

sunag commented Sep 14, 2022

@jstone-lucasfilm I don't know if MrDoob sees the same thing, but as we are developing WebGPURenderer we could study a way to port MaterialX and share the same algorithms for both WebGL and WebGPU, and I believe we can move forward in implementing a MeshStandardSurfaceMaterial from Autodesk for both backends.

abernier pushed a commit to abernier/three.js that referenced this pull request Sep 16, 2022
* add includes for constructor argument

* add support to array for function call

* add function interface

* convert to nodeObjects function call parameters and includes

* add fn

* add materialx noise functions example

* adjust scale to better visual
snagy pushed a commit to snagy/three.js-1 that referenced this pull request Sep 21, 2022
* add includes for constructor argument

* add support to array for function call

* add function interface

* convert to nodeObjects function call parameters and includes

* add fn

* add materialx noise functions example

* adjust scale to better visual
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants