NodeMaterial: Cannot set properties of undefined

Hello friends,

so… I created a Material like this:

import MeshStandardNodeMaterial from "three/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js"
...
new MeshStandardNodeMaterial()

and I get the following error when attempting to use the material:

three.cjs:20208 Uncaught TypeError: Cannot set properties of undefined (setting 'value')
    at getProgram (three.cjs:20208:1)
    at setProgram (three.cjs:20326:1)
    at WebGLRenderer.renderBufferDirect (three.cjs:19758:1)
    at renderObject (three.cjs:20150:1)
    at renderObjects (three.cjs:20126:1)
    at renderScene (three.cjs:20066:1)
    at WebGLRenderer.render (three.cjs:19955:1)
   <snip (my code)>

I am not sure why cjs version is being used or whether there is also an esm version out there. Anyways, the line where the stack trace originates form corresponds to this source line:

I also attempted to construct material like this - to skip the whole “needsLights” section:

import MeshBasicNodeMaterial from "three/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js"
new MeshBasicNodeMaterial({
        lights: false
});

In that case I receive an similar error from here

We are talking about rather trivial example, not sure what could be wrong. Replacing node material with a “normal” material works properly. The rendered geometry has the usual attributes: position, uv, normal and color.

Any advice? Cheers.

Update: Following works:

    const uniforms = UniformsUtils.clone(ShaderLib.standard.uniforms)

    new MeshStandardNodeMaterial({
        uniforms
    });

Is it what one is supposed to do?

Also there seem to be no lights and everything is red (as #f00). Not great. Will do more experiments.

Sad update. No progress from yesterday. I managed to make a separate project for experiments. Full source is as follows:

import * as THREE from 'three';
import * as Nodes from 'three/examples/jsm/nodes/Nodes.js';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.z = 5;

const uniforms = THREE.UniformsUtils.clone(THREE.ShaderLib.standard.uniforms)
const material = new Nodes.MeshBasicNodeMaterial({ uniforms })

material.colorNode = new Nodes.ConstNode(new THREE.Color(0, 1, 0), Nodes.NodeType.Color);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

function animate() {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;


    renderer.render(scene, camera);
    requestAnimationFrame(animate);

};

animate();

Another update:

Double checking the examples, a possible missing part is:

import { nodeFrame } from 'three/examples/jsm/renderers/webgl/nodes/WebGLNodes.js';
...
nodeFrame.update();

However, that does not compile, because WebGLNodeBuilder.js imports three-nodes, unfortunately that seems to be relic of the past and the files are gone. There’s an npm package three-nodes in version 0.0.0 however doesn’t contain anything useful.

Success!

The correct solution involves using nodeFrame + following webpack configuration.

    resolve: {
        alias: {
            'three-nodes': path.resolve('node_modules/three/examples/jsm/nodes')
        }
    }

Hm. It’s all in the examples, in fact.

1 Like