GLTF Model (from 3DS exporter) does not generate shadows, faces may be flipped

Hi guys, I’m new to Babylon, but I’ve been using Three.js for years.
I trying to load models in GLTF 2 format and I want them to cast and receive shadows.
But I can’t figure out what’s wrong.
Searching the documentation I found that I should

  1. add each mesh that should generate shadows, to the shadow generator render list
  2. set “receiveShadows” to true on each mesh

Here is a screenshoot of the test I’ve done.
The teapot is loaded from the GLTF and does not receive or generate shadows. The material comes from a 3DS Max Physical Material

Here is the code
var canvas = document.getElementById(“renderCanvas”); // Get the canvas element
var engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

    /******* Add the create scene function ******/
    var createScene = function () {

        var scene = new BABYLON.Scene(engine);

        var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI/3, Math.PI / 4, 200, new BABYLON.Vector3(0,0,0), scene);
        camera.attachControl(canvas, true);

        var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
        myMaterial.diffuseColor = new BABYLON.Color3(1, 0.5, 1);
        myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);

        var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:10}, scene);
        sphere.position=new BABYLON.Vector3(-20,10,0);            

        var sphere2 = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:5}, scene);
        sphere2.position=new BABYLON.Vector3(0,30,10);            

        var myPlane = BABYLON.MeshBuilder.CreatePlane("myPlane", {width: 1000, height: 1000}, scene);
        myPlane.position=new BABYLON.Vector3(0,-5,0);

        var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 50, 0), scene);
        var light2 = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(0, 100, 0), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 10, scene);
        light2.falloffType = BABYLON.Light.falloff_physical;
        light2.specular = new BABYLON.Color3(1, 1, 0.8);    

        var shadowGenerator = new BABYLON.ShadowGenerator(1024, light2);
        shadowGenerator.usePoissonSampling = true;
        shadowGenerator.getShadowMap().refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE;

        var loader=BABYLON.SceneLoader.LoadAssetContainer("./models/", "teapot.gltf", scene, function (container) {
            var meshes = container.meshes;
            var materials = container.materials;


            for (var i=0;i<meshes.length;i++){    
        loader.compileMaterials = true;            

        var scene = createScene(); //Call the createScene function

        engine.runRenderLoop(function () { 

        window.addEventListener("resize", function () { 

I suspect it has something to do with the faces been flipped beacuse if I overrride the material of the teapot with a Babylon material (after the loading of the GLTF has completed) It only shows the backfaces of each triangle

Any ideas?

Hi and welcome.

Well, I don’t want to ask an obvious question, but did you try flipping faces inside 3dsMax? :smiley:

I did try, but the mesh still appears insideout when assigning a Babylon material.

At a lower level, in WebGL, the sides of each face (forward face or back face), depend on the order the vertices appear on the buffer.The normal attribute only affects ilummination calculations.

Here is a screemshot

Try setting backFaceCulling to false on babylon material.

But that won’t help you with the shadow tho. For that try setting the position of the light after the light is defined. I am not sure for the spotlight but for example when using directionalLight you have to set position of the light to see shadows.

so light.position = new BABYLON.Vector3(x,y,z);

You can also try to play with the bias parameter

I tried but no luck.
I also tried with a .babylon file, but the problem is the same, no shadow casting from the loaded model

Can you create Playground with that model.and your code? It would be helpful in finding solution.

This is not related to the faces as gltf files are right handed and Babylon.js applies an inversion for you so it works in babylon.js scene which is left handed.

This is maybe related with something wrong with the assets container. Do you mind reproduce the error in the playground as @nogalo mentioned?
Here is a doc to reference external assets: Using External Assets - Babylon.js Documentation

Hi, I’ve uploaded a test to the playground.

I found that the issue with the shadows is fixed if I create the ShadowsGenerator after the model is loaded.

But the other issue with the faces is still there when I overwrite the material. If I leave the material that comes from the GLB, it works fine.

setting backFaceCulling to false on line 14 seems to fix the problem. Is that what you wanted?

Also just out of curiosity I recreated scene with your original code (it was weird to me that you had to load model first and then to create shadowGenerator because it should work even if you create it before).

What I discovered is this

It works, but if you uncomment line 44 where is refreshRate setting (which is existing in your original code), then it doesn’t work.

So without that you can use your old code and everything is okay.


Okay you can also use that line but like this.

shadowGenerator.getShadowMap().refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONEVERYFRAME

Or REFRESHRATE_RENDER_ONEVERYTWOFRAMES which is probably more performance acceptable

Instead of REFRESHRATE_RENDER_ONCE like you had in your original code.

Unfortunatelly I’m not master of shadows, so they are still looking not very well, but at least
it is working with materials from your asset :wink:
@nogalo was right, first you have to turn off backFaceCulling, and to get shadows on the glb objects you have to turn off PhysicalLightFalloff too.

Yes, that workaround is fine. But on a large model that will hurt performance.
For some reason the loader is reversing the facing of each triangle.
But if I use the .babylon format it works fine

Thanks, that makes sense.
If you set ShadowsGenerator to render them only once, They are computed before the GLB is loaded so the teapot dows not appear in the shadowmap.

May be there is a method to manually update the shadowmap once the teapot is added

It seems, that it works if you put it after the mesh is loaded, which makes sense as you said, after the mesh is loaded compute the shadow once and that’s it.

Also here is a docs part for this that might interest you.

1 Like