Scene not rendering with MeshPhongMaterial

This sounds like a really basic question, but it has me stumped. I’ve been out of the game for a while, but I don’t think my skills have rusted that far…

A lot of StackOverflow questions are starting to relate to modules. Stack Overflow’s snippets don’t support JS modules within the JavaScript pane, so I’m updating my answer template code to use script tags which let me use type="importmap"/type="module". This works, mostly. Here’s an example:

<script type="importmap">
	{
		"imports": {
			"three": "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.163.0/three.module.js"
		}
	}
</script>

<script type="module">
	import {
		WebGLRenderer,
		Scene,
		PerspectiveCamera,
		PointLight,
		SphereGeometry,
		MeshBasicMaterial,
		Mesh
	} from 'three'

	const renderer = new WebGLRenderer()
	document.body.appendChild( renderer.domElement )
	const camera = new PerspectiveCamera( 25, 1, 1, 100 )

	function resizeToWindow () {
		if ( renderer && camera ) {
			renderer.setSize( window.innerWidth, window.innerHeight )
			camera.aspect = window.innerWidth / window.innerHeight
			camera.updateProjectionMatrix()
		}
	}
	window.addEventListener( 'resize', resizeToWindow )

	//resizeToWindow()
	/* DEBUG */ renderer.setSize( 500, 500 )

	const scene = new Scene()
	const light = new PointLight( 0xffffff )

	camera.add( light )
	scene.add( camera )
	camera.position.set( 0, 0, 50 )
	camera.lookAt( scene.position )

	const geo1 = new SphereGeometry( 5 )
	const mat1 = new MeshBasicMaterial( {
		color: 'red'
	} )
	const msh1 = new Mesh( geo1, mat1 )
	scene.add( msh1 )

	renderer.render( scene, camera )
</script>

This is literally all I have in the snippet, and it works great! I see a single, red, solid-color sphere in the center of my viewport.

The problem occurs when I replace MeshBasicMaterial with MeshPhongMaterial. That’s it. That’s the only change, and then the sphere no longer renders.

  • I have a light
    • It’s attached to my camera
  • The light (in the camera) is in the scene
  • The mesh is in the scene

I tried adding the light to the scene directly, but it didn’t make a difference.

I copied my code to a standalone HTML file, dropping the script tags into the <body>, but I got the same results as in the snippet.

I double-checked the docs, and it seems like I should be able to define MeshPhongMaterial with only color, or even with no parameters (the docs say it should default to white). I removed the parameter object, but it didn’t make a difference.

Edit: I don’t get any errors in the console. CORS obviously isn’t an issue, otherwise it wouldn’t be rendering with MeshBasicMaterial. I have also double-checked for typos. :slight_smile:

So, what super-simple thing am I missing or doing wrong?

Your code looks ok and seems to work as expected on codepen ?

preview

Are you importing MeshPhongMaterial before using it?

import {
	WebGLRenderer,
	Scene,
	PerspectiveCamera,
	PointLight,
	SphereGeometry,
	MeshBasicMaterial,
	MeshPhongMaterial, // NOTE <- Import the material from three, this is not automatic when working with modules
	Mesh
} from 'three'

It’s not, though. You haven’t reproduced my environment/configuration. I’ll go into the differences below, but in order to reproduce what I’m seeing, create a blank codepen then:

  1. Copy/paste MY CODE into the HTML panel
  2. When it executes you’ll see a red circle (sphere)
  3. Change MeshBasicMaterial to MeshPhongMaterial
  4. When it executes you’ll see, well, nothing because the sphere no longer renders

Regarding your code comment, I understand that I need to include MeshPhongMaterial in my list of imports. When I made the switch from MeshBasicMaterial, I replaced it with MeshPhongMaterial in both the import and in the new line.

Difference Details

1. You aren’t importing in the codepen.

Your HTML:

<script src="//cdn.jsdelivr.net/gh/mrdoob/three.js@r151/build/three.js"></script>

Your JS:

const {
	WebGLRenderer,
	Scene,
	PerspectiveCamera,
	PointLight,
	SphereGeometry,
	MeshBasicMaterial,
	MeshPhongMaterial,
	Mesh
} = THREE;

This is a destructuring assignment from the es5 THREE object. It’s equivalent, but not the same as an es6 import. Still, I doubt the difference is relevant.

2. Code location

You placed the JS code in the JS pane. I’d love to do this, but my environment (StackOverflow snippets) doesn’t allow modules in its JS code pane.

Lights have changed. Increase the intensity of the light. Does it make a change?

const light = new PointLight( 0xffffff, 5000 );
3 Likes

There it is!

I see the change was introduced in r155. I’ll have a look at the new systems and get acquainted with them. Thanks!

Related: Updates to lighting in three.js r155

2 Likes