shadowOnlyMaterial can not be created

I am using Babylonjs in an Vuejs project. I want to create a transparent ground which can receive shadows. I have loaded the @babylonjs/materials library.

Here is the code:

import { ShadowOnlyMaterial } from “@babylonjs/materials/shadowOnly/shadowOnlyMaterial”;

const ground = BABYLON.MeshBuilder.CreatePlane(“ground”, { height: 3, width: 3 });
ground.material = new ShadowOnlyMaterial(‘mat’, scene);

When I run the project I get the following error:
material.js?0c4d:220 Uncaught (in promise) TypeError: this._scene.getEngine(…).createMaterialContext is not a function
at ShadowOnlyMaterial.Material (material.js?0c4d:220:1)
at ShadowOnlyMaterial.PushMaterial [as constructor] (pushMaterial.js?c0c1:12:1)
at new ShadowOnlyMaterial (shadowOnlyMaterial.js?9c5f:39:1)

When I check the engine I can not see any function “createMaterialContex”. The shadows of meshes on planes with StandardMaterial are working fine.

It might be a simple mistake I made. But what mistake?
Thanks a lot for help!

1 Like

I thought it is a problem of versions. I installed 5.2.0 for core, materials and loaders. It still does not work.

Funny thing: in Playground with version 5.2.0 the code works fine and I noticed the BABYLON module has the function ShadowOnlyMaterial. On my own environment, same BABYLON version does not have that function. Is this a bug???

Interesting. I’m gonna bookmark this. From my understanding there was no ‘shadowOnlyMaterial’ as of now declared as a class of materials in the API. The BJS shadowOnlyMaterial is simply an extrapolation of the backgroundMaterial with nothing else than a shadowColor . I’d love to hear about the new class of shadowOnlyMaterial (if it exists)?…

@mawa : I am not very experienced with Babylonjs, but should I understand that there is another way to set the material to be fully transparent but still showing the shadows?

Sry for late reply. I wasn’t here for a couple of days.
I think I spotted your error (may be you did meanwhile).
When you call the material, you forgot to put the namespace BABYLON:

Where:
ground.material = new ShadowOnlyMaterial(‘mat’, scene);

Should read:
ground.material = new BABYLON.ShadowOnlyMaterial(‘mat’, scene);

That should do it.

And what I was saying is that there is no class of this material in the API. The material is based on the backgroundMaterial. Doesn’t change anything though. It should work when called correctly.

Thank you mawa! However, I wish it would be that easy. I used the version without BABYLON when I imported it:

import { ShadowOnlyMaterial } from “@babylonjs/materials/shadowOnly/shadowOnlyMaterial”;

The BABYLON module (5.2.0) does not expose a class “ShadowOnlyMaterial” so, when I use it I get a clear error:

babylonjs_core__WEBPACK_IMPORTED_MODULE_12_.ShadowOnlyMaterial is not a constructor

Since BABYLON 5.2.0 from the Playground does have that class, I suspect that for some reason, the npm package for 5.2.0 (@babylonjs/core) does not include that class.

But you suggested that it is actually a backgroundMaterial. I will try to work around using that class. Thanks!

I tried the backgroundMaterial, but it does not show the shadows when it is set to be transparent.

Apologies, I didn’t realize the webpack and npm package part.
However, did you try import all materials and then use the shadowOnlyMaterial and it doesn’t work?
Since it appears there is no class in the API for the shadowOnlyMaterial I thought it must have been inheritated from the backgroundMaterial, though it might also have other dependencies.
Using the backgroundMaterial only for shadows will likely not work, although I’d like to try something and will let you know.
And then, Did you try with a legacy webpack (like 4.2.1)?
It appears the link shown in the doc to the material in github is broken. Files may have been moved or renamed.

Edit: may be @Evgeni_Popov can help you with this issue. Let’s see what he can tell you about it.

I did try with all materials from @babylonjs/materials imported, but did not change the result.

Originally I used Babylon 4.2. Then I changed to 5.2 hoping to solve the problem. Not sure if this might be also an issue, but my project is in Vue.js (webpack is under Vue).

I have some work-around for this shadow problem, but involves complex image projections, such as the shadow will fall onto a non-transparent plane. However, I would prefer the straightforward option. So I really appreciate your interest for this subject and I am looking forward to hear if there is some simpler solution.
(btw: I moved from Three.js to Babylon for many of its nice features. But this one - the shadow on a transparent plane - works like a charm in Three.js :slight_smile: )

This looks like a bug, cc @RaananW to have a look on Monday when he ll be back from his break.

from your code it looks like your are mixing BABYLON. usage and @babylonjs/materials, you might be using the npm babylonjs and @babylonjs/materials.

You should either use:
@babylonjs/core and @babylonjs/materials
or
babylonjs and babylonjs-materials
but never mix and match the flavors :slight_smile:

If not, and BABYLON comes from an import of all core, could you try renaming the variable ?

Yes @sebavan, you certainly explained it better than I did, but that was my thought. On the other hand, I’m not using webpacks :wink:

@Mircea_H I did try to twist a background or standard material to display shadows only, but had no luck with that. Definetely, the shadowOnlyMaterial would be the way to go - so I do hope someone in this forum will (soon) have the right answer for your issue.
Meanwhile, GL with your project and have a great WE,

@mawa @sebavan Thank you guys for trying to find the cause of this. For when you will dig more into the problem, here are some more details:

I did use only @babylonjs/core and @babylonjs/materials. Here are the project dependencies (maybe you can see some incompatibilities):

“dependencies”: {
@aws-amplify/ui-components”: “^1.9.6”,
@aws-amplify/ui-vue”: “^2.0.5”,
@babylonjs/core”: “^5.2.0”,
@babylonjs/loaders”: “^5.2.0”,
@babylonjs/materials”: “^5.2.0”,
“aws-amplify”: “^4.3.10”,
“bootstrap”: “^5.1.3”,
“bootstrap-icons”: “^1.7.2”,
“core-js”: “^3.6.5”,
“vue”: “^3.0.0”,
“vue-router”: “^4.0.0-0”,
“vuex”: “^4.0.0-0”
},

I changed the import name for materials:

import * as BABYLON from “@babylonjs/core”;
import * as MATERIALS from “@babylonjs/materials”;

Then I run:

const ground = BABYLON.MeshBuilder.CreatePlane(“ground”, { height: space.room_d, width: space.room_w });
ground.rotation.x = Math.PI / 2;
ground.position.x = space.room_w / 2;
ground.position.z = -space.room_d / 2;
ground.material = new MATERIALS.ShadowOnlyMaterial(‘mat’, scene);
ground.receiveShadows = true;

This triggers a long list of errors (a couple of pages). Here is the beginning:

logger.js?bb23:87 BJS - [13:52:50]: Unable to compile effect:
Logger._ErrorEnabled @ logger.js?bb23:87
Effect._processCompilationErrors @ effect.js?67a6:628
Effect._checkIsReady @ effect.js?67a6:427
eval @ effect.js?67a6:431
setTimeout (async)
Effect._checkIsReady @ effect.js?67a6:430
Effect._prepareEffect @ effect.js?67a6:598
Effect._useFinalCode @ effect.js?67a6:265
eval @ effect.js?67a6:207
eval @ shaderProcessor.js?13a1:35
ShaderProcessor._ProcessIncludes @ shaderProcessor.js?13a1:380
ShaderProcessor.Process @ shaderProcessor.js?13a1:30
shadersLoaded @ effect.js?67a6:202
eval @ effect.js?67a6:225
eval @ fileTools.js?4c51:348
onReadyStateChange @ fileTools.js?4c51:462
XMLHttpRequest.send (async)
WebRequest.send @ webRequest.js?2ac9:146
retryLoop @ fileTools.js?4c51:488
requestFile @ fileTools.js?4c51:490
RequestFile @ fileTools.js?4c51:524
LoadFile @ fileTools.js?4c51:347
ThinEngine._loadFile @ thinEngine.js?875d:4594
Effect._loadShader @ effect.js?67a6:472
Effect @ effect.js?67a6:222
ThinEngine.createEffect @ thinEngine.js?875d:2272
ShadowOnlyMaterial.isReadyForSubMesh @ shadowOnlyMaterial.js?9c5f:168
Mesh.isReady @ mesh.js?c003:985
Mesh._this._internalMeshDataInfo._onMeshReadyObserverAdded @ mesh.js?c003:298
Observable.add @ observable.js?a6cf:194

At this stage, I can only advise to wait for the big brains :wink: and very dedicated people :grinning: at BJS to have a closer look into this. This is simply beyond my expertise. I only quickly noticed that some fixes have been made for v5 to relink with materials. May be something is missing there for this special type of material, for the npm package or may be you are messing up something with the import. If it was me, I would rather continue working on other parts of the project and wait for an answer from the council @sebavan @RaananW . Shouldn’t be all too long…

Sure, I understand. And I really appreciate the time you have spent into this!

Hey! And sorry for the late reply :slight_smile:

Would you be able to share the project so I can look into what’s not working? I will check it locally as well, but just to be sure I am reproducing this correctly it would be great if you could.

It seems like a shader that is not being loaded.

Oh, and just in case it sounded otherwise - I have a feeling it’s on our side, and nothing you are doing incorrectly.

Ok, quick update - I managed to use the shadow-only-material in an es6 project so it would be great to see a reproduction of your project to know what the issue is.

1 Like

I wonder if it might be import * as BABYLON could you try renaming it in import * as TOTO instead as the BABYLON name could shadow smthg ???