Exporting models/scenes from Houdini to three.js?

Hi; I’m thinking about developing a workflow with artists working in Houdini to develop assets for a three.js application: I’d like them to be able to export entire scenes (objects, materials, textures, lights, and animations) but even just object/material/texture would be OK. Houdini doesn’t export glTF (too bad!); does anyone here have experience with this workflow? Any tips?

The proper workflow would be to somehow target GLTF. If you can export to some other format like collada or fbx you could convert this to GLTF via a script. There were examples of various package specific exportes that would export to json, but it being json you don’t have to limit yourself to any particular format, but rather what suits your needs. GLTF seems like the most supported format in Three.js and aims to be the standard for web transfer anyway,

I would try some combination of:

I think those should preserve most of what you describe, lights are not yet finalized in glTF though.

1 Like

Houdini 17 will add direct import/export of glTF: https://vimeo.com/291934239 (about 7:00)

3 Likes

Good news :slight_smile: :+1:

Hey all! Reviving this thread. Trying to find a streamline a workflow from Houdini to ThreeJS.

Houdini does now have GLTF/GLB exporter which allows for Houdini’s principle shader to come along for the ride (great).

The principle shader port seems a bit basic and lacks functionality.

Houdini now is building around USD / MaterialX (great)!

Has anyone gotten a MaterialX export, from Houdini, working in a ThreeJS scene? I’ve been struggling with doings so using vanilla ThreeJS and it seems resources on this topic are far and few in-between.

My backup plan here is to just rebuild materials w/ ThreeJS Standard and Physical materials, but it would be a lot more straightforward to just export .mtlx files from Houdini and reference them into ThreeJS.

Am I barking up the wrong tree with MaterialX and ThreeJS? Any guidance here would be welcome.

Thank you!

three.js does have a MaterialX loader:

https://threejs.org/examples/?q=materialx

But (1) I doubt we’ve tested it against .mtlx exports from Houdini, please feel free to report bugs and share those materials! Probably most issues like that can be fixed.

And (2) currently USDZLoader is focused on the subset of USD features that Apple’s viewers support. Not the whole USD format, which is fairly open-ended and usually tailored for specific companies’ pipelines. So USDZLoader doesn’t support MaterialX materials today. You could file a feature request about that, I’m not sure how complex it would be or how the loader’s maintainers feel about it.

Thank you for the reply.

Just as a gut-check, below is how I’m loading in a .mtlx and assigning it. Sloppy code from someone fairly new to JS/ThreeJS, but with Python, C# and VEX background.

No console errors, but my model just disappears and the scene loads. Tried the same approach with a MeshStandard material and that worked as expected. Do you see anything that shouts out at you as not right? This is not the entire solution, just the main bits using MaterialXLoader. Thanks for any guidance.

EDIT: attached the mtlx file coming out of Houdini. Also tested this with mtlx files downloaded from AMD library. No joy.

Another Edit: Attached in a zip is the .mtlx set I downloaded from https://matlib.gpuopen.com. Same behavior as the “simple.mtlx”, but console log barks a warning.
TH_Wood_Table_1k_8b.zip (4.5 MB)


simple.mtlx (3.3 KB)

import { MaterialXLoader } from 'three/examples/jsm/loaders/MaterialXLoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'

const gltfLoader = new GLTFLoader()
const rgbeLoader = new RGBELoader()
const mtlxLoader = new MaterialXLoader()
.........
........
const SAMPLE_PATH = '/mtlx/simple.mtlx'
gltfLoader.load(
    '/models/matball.glb',
    (gltf) =>
    {
        const material = mtlxLoader.load(SAMPLE_PATH, (m) =>{
        scene.add(gltf.scene)
        scene.traverse((child) =>
        {
            if(child.isMesh)
            {
                child.material = m
            }
        })

        })
    }
)

The MaterialX loader returns an object with a .materials property, so you may need to log that and see what (if anything) it found in the file. Personally I find it easiest to deal with this async stuff in async/await syntax:

const [gltf, mtlx] = await Promise.all([
  gltfLoader.loadAsync('models/matball.glb'),
  mtlxLoader.loadAsync(SAMPLE_PATH)
]);

console.log(mtlx);

scene.add(gltf.scene);

gltf.scene.traverse((child) => {
  // ...
});

Thank you for the example and trying to help. There is an object definitely returned -

As long as I’m assigning it correctly (regardless of using async or not), that tells me something isn’t working right?

When I have more time I’ll create a demo project and post it up here. MaterialX in ThreeJS would be a real treat.

That looks like a material in your screenshot. Keep in mind a mtlx could have multiple materials, you need to select one. Whether it’s the ‘right’ material I don’t know, but you can inspect it:

const material = mtlx.materials.NG_tester_surfaceshader_displacementshader;

gltf.scene.traverse((child) => {
  if (child.isMesh) {
    child.material = material;
  }
});

If it looks different than you think it should, may be necessary to share the .mtlx.

Did not realize that the return of the MaterialXLoader was an object that contained multiple materials! Thank you for pointing that out.

Now I am actually assigning the mtlx material type object to the mesh. Attached are two json files that show a console log of both the mtlx material objects.

AMD_mtlx_object.json (4.8 KB)
simple_mtlx_object.json (2.9 KB)

The objects themselves seem to be loading in alright, but upon assigning them to the mesh, I’m getting the following errors -

For the AMD mtlx I’m testing with -

Uncaught TypeError: uniforms.ambientLightColor is undefined

For the Houdini mtlx I’m testing with -

Uncaught TypeError: uniforms.opacity is undefined

Appreciate your time and patience. When you have a moment let me know if if you have any suggestions for these new errors on assignment OR if this is a deeper issue that may be indicative of a ThreeJS mtlx support issue.

This is how I’m assigning the material in the mtlx object container which could contain multiple materials -

child.material = m.materials.NG_tester_surfaceshader

I think it’s very likely your .mtlx file is using some features of the MaterialX format that the three.js loader has never seen before, we haven’t tested on Houdini’s MaterialX exports.

I’d recommend filing a feature request on the three.js GitHub repository, and attaching the .mtlx file you exported from Houdini. We’ll have to take a look to see what can be done to support it. If you can include any details about how it was created in Houdini — can the free Houdini plans export .mtlx? — that might also be very helpful.

The JSON files above are stringified THREE.Material class instances … there’s not so much we can debug from that, we’d need the source .mtlx file.