Syntax Error when try to use ProjectedMaterial

I try to work with Marco Fugaro’s three-projected-material. I set my imports as follows:

import * as THREE from 'https://unpkg.com/three@0.122.0/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three@0.122.0/examples/jsm/controls/OrbitControls.js';
import ProjectedMaterial, { project } from 'https://unpkg.com/three-projected-material';

But at the point I try to project the texture to a box (geometry and material defined well before):

const box = new THREE.Mesh(geometry, material);
project(box);

I get the following error message:
SyntaxError: The requested module 'https://unpkg.com/three-projected-material' does not provide an export named 'project'

although a function project is defined inside.
Can anybody explain how set it up correctly?

Thanx in advance for help.
bluefox67

(1) Keep in mind the repo was not updated for the past year - it uses three@0.111.0, while the version you are using is three@0.122.0 (it doesn’t mean it won’t work, just a thing to remember if stuff started to fail.)

(2) Importing:

https://unpkg.com/three-projected-material

redirects you to:

https://unpkg.com/three-projected-material@1.1.0/build/ProjectedMaterial.js

and results in importing this file. Since you’re using import instead of <script> tags, what you wanted to import is probably this file (source.) Try changing the import url to:

https://unpkg.com/three-projected-material@1.1.0/build/ProjectedMaterial.module.js

If I do so, I get the error
TypeError: Failed to resolve module specifier “three”. Relative references must start with either “/”, “./”, or “…/”.

Do you recommend to use tags instead of importing? In that case: Can I use the above URLs for THREE and OrbitControls, too?

As in the docs :face_with_head_bandage::

<!-- Use <script> to import CDN files -->
<script src="//unpkg.com/three"></script>
<script src="//unpkg.com/three-projected-material"></script>
<script>
  // Imported package exports everything to window.projectedMaterial
  const { default: ProjectedMaterial, project } = window.projectedMaterial;

  // Your code ...
</script>

I can’t test how it would work with script type="module" for you atm, but since you’re using CDNs - doing imports with script tags may be the easier way.

Ok. Thanx so far. I’ll try. :slightly_smiling_face:

Causes next messages:

Uncaught ReferenceError: require is not defined
    at three.js:1
(anonymous) @ three.js:1
three-projected-material:24 Uncaught TypeError: Cannot read property 'ShaderMaterial' of undefined
    at three-projected-material:24
    at three-projected-material:4
    at three-projected-material:5

Sorry, it should be unpkg.com/three instead of unpkg.com/three.js (three.js leads to three.js/shim.js)

Edited the post above for clarity.

Ok. This is better. :blush:
Just one more little thing: where are the OrbitControls located on unpkg.com?

unpkg inherits the structure from github repo. For example, this is the main three.js file:

https://unpkg.com/three@0.122.0/build/three.js

and OrbitControls are placed not in the build/, but in examples/ directory (both in the repo and on unpkg) :

https://unpkg.com/three@0.122.0/examples/js/controls/OrbitControls.js

Fine. Now declarations are working without error messages :+1:
But now, there is an error inside. I’ve loaded a texture image (png) and scaled the textureScale to 0.8 (as recommended in the example).
But there is an error saying:

Uncaught TypeError: Cannot read property 'naturalWidth' of undefined
    at computeScaledDimensions (three-projected-material:194)
    at new ProjectedMaterial (three-projected-material:56)

What’s wrong there?

Are you sure you did load it? The only place I can see in the ProjectedMaterial’s code that would throw that error - is when you pass a texture that hasn’t been loaded.

Yes, sure:
var texture = new THREE.TextureLoader().load('./test.png');

and

            ...
            const geometry = new THREE.BoxGeometry(1, 1, 1);
			const material = new ProjectedMaterial({
			  camera, // the camera that acts as a projector
			  texture, // the texture being projected
			  color: '#cccccc', // the color of the object if it's not projected on
			  textureScale: 0.8, // scale down the texture a bit
			  cover: true, // enable background-size: cover behaviour, by default it's like background-size: contain
			})
			const box = new THREE.Mesh(geometry, material);
			scene.add(box);

			// and when you're ready project the texture!
			project(box);

Did you try using a callback of TextureLoader.load (docs) ?

Texture loading is asynchronous, so just calling load does not ensure that the texture exists right away. You can see in the texture loader source, that texture.image is defined only after the image is actually loaded. Before that, texture image is set to Texture.DEFAULT_IMAGE (which, unless you changed it, is undefined.)

OK. Building this using a callback function

            var texture = new THREE.TextureLoader().load(
				// resource URL
				'./test.png',

				// onLoad callback
				function ( texture ) {
					// in this example we create the material when the texture is loaded
					const material = new ProjectedMaterial({
					  camera, // the camera that acts as a projector
					  texture, // the texture being projected
					  color: '#cccccc', // the color of the object if it's not projected on
					  textureScale: 0.8, // scale down the texture a bit
					  cover: true, // enable background-size: cover behaviour, by default it's like background-size: contain
					});
				},

				// onProgress callback currently not supported
				undefined,

				// onError callback
				function ( err ) {
					console.error( 'An error happened while loading texture.' );
				}
			);
			
			const box = new THREE.Mesh(geometry, material);

I get an error for the last line:

Uncaught ReferenceError: material is not defined.

It seems like this line will be reached before the callback is done …

Please keep in mind, three is probably not a good library to learn javascript with. It’s easier to first learn technicalities of js, and then jump to technicalities of three: