Jump to content

Shadow issues..


nittrus
 Share

Recommended Posts

1cf477093c2ebcf4813e99f1dcfb033c.png

OK so I have this endless chunked terrain where I am walking around, I head out a ways, the sun/light objects are moving with the player as I move keeping it's orbit and direction pointed toward the player model, but for some reason the shadows start to go off to the wrong side and distorts (see above image)!

Is there a way to tell the shadow generator the light position and target has updated because it looks like it isn't updating since it was instantiated. I'd think it would auto update or something each frame to make sure it was following the light source properly, but that doesn't seem to be the case here.

Is there something like shadow generator.update() or something I'm missing?
How would I get this to work right, it is bugging me!

Here is the bit of code that updates the sun/light position pre-calculated before frame render, less global variables of course..

scene.beforeRender = function (){
	skybox.rotate(BABYLON.Axis.Z, -0.00008, BABYLON.Space.PIVOT);
	if(sunmove && actor){
	sunvls.mesh.position = new BABYLON.Vector3(actor.position.x + sunorbdis * Math.sin(sunorbdelta), actor.position.y + sunorbdis * Math.cos(sunorbdelta), actor.position.z);
	light.position = sunvls.mesh.position;
	sunorbdelta += sunspeed;
    }
};

How can I work in shadow generator update?

Thanks!

Link to comment
Share on other sites

Well, there is one of my hacks, for a problem very similar to yours.
This sets the size and direction of the light's shadowgenerator to a "shadowMesh", and not the bounding box of all the meshes in the scene.
I move and size this shadowMesh with the camera.
Maybe it is time to make a PR from this too, I encountered many problems and the lack of cascading (and camera following) shadow was one of them.

 

BABYLON.DirectionalLight.prototype.setShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
   var orthoLeft = Number.MAX_VALUE;
   var orthoRight = Number.MIN_VALUE;
   var orthoTop = Number.MIN_VALUE;
   var orthoBottom = Number.MAX_VALUE;
   var tempVector3 = BABYLON.Vector3.Zero();
   var activeCamera = this.getScene().activeCamera;

   var hasShadowMesh = (typeof this.shadowMesh != 'undefined'); //size shadow Map to this.shadowMesh only (local area)

   // Check extends
   for (var meshIndex = 0; meshIndex < renderList.length; meshIndex++) {
      var mesh = renderList[meshIndex];
      if (hasShadowMesh) { //only check shadowMesh
         mesh = this.shadowMesh;
         meshIndex = renderList.length+1;
      }
      if (!mesh) {
         continue;
      }
      var boundingInfo = mesh.getBoundingInfo();
      if (!boundingInfo) {
         continue;
      }
      var boundingBox = boundingInfo.boundingBox;
      for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
         BABYLON.Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
         if (tempVector3.x < orthoLeft)
            orthoLeft = tempVector3.x;
         if (tempVector3.y < orthoBottom)
            orthoBottom = tempVector3.y;
         if (tempVector3.x > orthoRight)
            orthoRight = tempVector3.x;
         if (tempVector3.y > orthoTop)
            orthoTop = tempVector3.y;
      }
   }
   var xOffset = orthoRight - orthoLeft;
   var yOffset = orthoTop - orthoBottom;
   BABYLON.Matrix.OrthoOffCenterLHToRef(orthoLeft - xOffset * this.shadowOrthoScale, orthoRight + xOffset * this.shadowOrthoScale, orthoBottom - yOffset * this.shadowOrthoScale, orthoTop + yOffset * this.shadowOrthoScale, -activeCamera.maxZ, activeCamera.maxZ, matrix);
};
Link to comment
Share on other sites

The other thing is the shadow bias.
It has to be set, but the good setting depends on the size of the shadow.

My settings now:

var light = this.sun;
this.shadowGenerator = new BABYLON.ShadowGenerator(mapsize, light);
this.shadowGenerator.getShadowMap().refreshRate = 1;
this.shadowGenerator.setTransparencyShadow(true);
this.shadowGenerator.useBlurVarianceShadowMap = true;
this.shadowGenerator.blurBoxOffset = 1.0;
this.shadowGenerator.blurScale = 1.0;
this.shadowGenerator.bias = 0.01;
Link to comment
Share on other sites

5 minutes ago, BitOfGold said:

Well, there is one of my hacks, for a problem very similar to yours.
This sets the size and direction of the light's shadowgenerator to a "shadowMesh", and not the bounding box of all the meshes in the scene.
I move and size this shadowMesh with the camera.
Maybe it is time to make a PG from this too, I encountered many problems and the lack of cascading (and camera following) shadow was one of them.

 


BABYLON.DirectionalLight.prototype.setShadowProjectionMatrix = function (matrix, viewMatrix, renderList) {
   var orthoLeft = Number.MAX_VALUE;
   var orthoRight = Number.MIN_VALUE;
   var orthoTop = Number.MIN_VALUE;
   var orthoBottom = Number.MAX_VALUE;
   var tempVector3 = BABYLON.Vector3.Zero();
   var activeCamera = this.getScene().activeCamera;

   var hasShadowMesh = (typeof this.shadowMesh != 'undefined'); //size shadow Map to this.shadowMesh only (local area)

   // Check extends
   for (var meshIndex = 0; meshIndex < renderList.length; meshIndex++) {
      var mesh = renderList[meshIndex];
      if (hasShadowMesh) { //only check shadowMesh
         mesh = this.shadowMesh;
         meshIndex = renderList.length+1;
      }
      if (!mesh) {
         continue;
      }
      var boundingInfo = mesh.getBoundingInfo();
      if (!boundingInfo) {
         continue;
      }
      var boundingBox = boundingInfo.boundingBox;
      for (var index = 0; index < boundingBox.vectorsWorld.length; index++) {
         BABYLON.Vector3.TransformCoordinatesToRef(boundingBox.vectorsWorld[index], viewMatrix, tempVector3);
         if (tempVector3.x < orthoLeft)
            orthoLeft = tempVector3.x;
         if (tempVector3.y < orthoBottom)
            orthoBottom = tempVector3.y;
         if (tempVector3.x > orthoRight)
            orthoRight = tempVector3.x;
         if (tempVector3.y > orthoTop)
            orthoTop = tempVector3.y;
      }
   }
   var xOffset = orthoRight - orthoLeft;
   var yOffset = orthoTop - orthoBottom;
   BABYLON.Matrix.OrthoOffCenterLHToRef(orthoLeft - xOffset * this.shadowOrthoScale, orthoRight + xOffset * this.shadowOrthoScale, orthoBottom - yOffset * this.shadowOrthoScale, orthoTop + yOffset * this.shadowOrthoScale, -activeCamera.maxZ, activeCamera.maxZ, matrix);
};

 

Uhm, no clue what you said there, been a programmer for 14+ years and that went over my head, lol

I am slightly new to BabylonJS not quite in the advanced phase.

Link to comment
Share on other sites

5 minutes ago, BitOfGold said:

The other thing is the shadow bias.
It has to be set, but the good setting depends on the size of the shadow.

My settings now:


var light = this.sun;
this.shadowGenerator = new BABYLON.ShadowGenerator(mapsize, light);
this.shadowGenerator.getShadowMap().refreshRate = 1;
this.shadowGenerator.setTransparencyShadow(true);
this.shadowGenerator.useBlurVarianceShadowMap = true;
this.shadowGenerator.blurBoxOffset = 1.0;
this.shadowGenerator.blurScale = 1.0;
this.shadowGenerator.bias = 0.01;

I must have missed half of those in the documentation, I seen nothing about refresh rate before, perhaps that will cure the stuttering issue I was also seeing, on one side of the mesh before the sun went over it was very smooth moving then on the other side it went in 1 second shifts instead of smoothly.

Link to comment
Share on other sites

I noticed I was able to do this awhile back using Three.js as I was able to move the shadow camera, the shadow had an object "camera" it was generated from, is this at all possible or similar available in BabylonJS? I really need this in order for things to seem worth moving forward or not on the project.

If shadow generators are fixed to where they were instantiated unable to adjust to a fluid environment, it seems to me something is very lacking, one would have to have a fixed non-modern environment where everything takes effect in a given area, whereas modern games are heading toward a more dynamic approach and that is what I need and was hoping to pull off in WebGL environment, probably asking to much to soon perhaps. But it is literally only the shadows holding the progress back in my case, so I may continue anyways without shadows until they have more work done to support a more dynamic environment, just the realism gone out the window a bit..

Link to comment
Share on other sites

52 minutes ago, fluffrabbit said:

That hack is excellent proof that Babylon is not production-ready. Thank you. I think I have made up my mind to use something else.

Wow.

How dare BJS not please you in every way.  Of all the unmitigated audacity, eh?  Obviously, the all volunteer team, and given-free-out-of-the-kindness-of-his-heart primary author... has not realized just how important you you you are.  Truly appalling.

Geez, dude.  Get a grasp.  Just re-code the section that ate your lunch, making it how you you you want it to be.

Link to comment
Share on other sites

1 hour ago, fluffrabbit said:

That hack is excellent proof that Babylon is not production-ready. Thank you. I think I have made up my mind to use something else.

 

25 minutes ago, Wingnut said:

Wow.

How dare BJS not please you in every way.  Of all the unmitigated audacity, eh?  Obviously, the all volunteer team, and given-free-out-of-the-kindness-of-his-heart primary author... has not realized just how important you you you are.  Truly appalling.

Geez, dude.  Get a grasp.  Just re-code the section that ate your lunch, making it how you you you want it to be.

While I personally frustrated about the lack of proper working shadows, I agree with Wingnut, seriously, Three.js even has issues, but in my opinion BabylonJS was in a more ready state (and possibly still is) with more frequent updates, thus I decided for me I like it better and still do, it's overall more complete and even has an audio engine built-in, thus I made my choice. My complaint was more of a suggestion to migrate shadow generators to being object oriented so that they can be parented to camera's and the like so they are more dynamic.

If you are looking for something more production ready, anything HTML5 isn't quite there yet! We're playing around with bleeding edge here, we're jugling bloody knives, but we like that, why else would we be testing the limits, I'm personally doing something unprecedented with WebGL creating something along the lines of No Mans Sky just without the premature release and bugs out the arse.. LOL I was being told left and right, "you're doing that with HTML5? Not going to happen" well it's happening, already beaten several of the potential issues!

If you are going to keep switching between engines because of limitations, you will never release anything!
You need to learn to overcome limitations, get creative, think outside of the cube.. when a cube don't work use a freaking sphere.. or vice versa.

At least when using a graphics and audio engine instead of a "game" engine you have ALLOT more control.

Link to comment
Share on other sites

3 hours ago, BitOfGold said:

There is a possible solution.
The shadowGenerator is caching the shadow camera's matrix if the light direction or position does not change.

I do this to countereffect (every time my camera moves):


this.shadowGenerator._cachedPosition = false;
this.shadowGenerator._cachedDirection = false;

Sadly this didn't help :(
Thanks for the help and suggestions thus far!

Link to comment
Share on other sites

1 hour ago, fluffrabbit said:

That hack is excellent proof that Babylon is not production-ready. Thank you. I think I have made up my mind to use something else.

I find it as degrading to read something like this. Babylon is the most advanced WebGL engine.

I think that this is not Babylon that is in question but the user. Also no motor is 100% perfect, otherwise you have to create your own motor that correspond to what you want to do. Each engine has its qualities and default and you will always find something's wrong with an engine to another.

This engine is good for production, it can do amazing things if used in the right ways. We must not denigrate the engine which not is the cause.

Link to comment
Share on other sites

 

@Deltakosh

If you see the hack above (setShadowProjectionMatrix), I move and resize the shadow camera to a region, to a mesh (.shadowMesh) near the camera.
This way I have a region with high quality dynamic shadows which do not depend on the size of all the meshes in the scene.

Take a look at this image:

screenshot

(The race track is 1000x1000m, the shadow area size depends on the height of the camera but it is around 50x50m)
Without this, the shadowGenerator tries to shadow the whole scene, even with 2048x2048 shadow map it is half meter pixels.
Thats why I have to recalculate the matrix, because the camera is moving. (the light does not)

The only problem left with this, the dynamic shadow ends hardly. I need to make a soft edge of the shadowed area.


 

Edited by BitOfGold
Link to comment
Share on other sites

4 minutes ago, BitOfGold said:

If you see the hack above (setShadowProjectionMatrix), I move and resize the shadow camera to a region, to a mesh (.shadowMesh) near the camera.
This way I have a region with high quality dynamic shadows which do not depend on the size of all the meshes in the scene.

Take a look at this image:

screenshot

(The race track is 1000x1000m, the shadow area size depends on the height of the camera but it is around 50x50m)
Without this, the shadowenerator tries to shadow the whole scene, even with 2048x2048 shadow map it is half meter pixels.
Thats why I have to recalculate the matrix, because the camera is moving. (the light does not)

The only problem left wit this, the dynamic shadow ends hardly. I need to make a soft edge of the shadowed area.


 

 

Yeah my problem is the light source is moving, not fixed.
I tried to load in your code but no difference is observed yet no errors are seen either, so I'm not even sure it loaded in properly, not quite sure how to implement it.

Link to comment
Share on other sites

Interesting concept. I like it a lot. Maybe you should consider integrating in bjs (Need to think how though:))

@nittrus are you using a point light or a directional light? Do you mind creating a PG to repro the issue?

 

If directional light, the cache should be invalidated on every frame: https://github.com/BabylonJS/Babylon.js/blob/2a0c505951937132e926d2375c6ca28d39b19365/src/Lights/Shadows/babylon.shadowGenerator.ts#L393

This is where the matrix is built: https://github.com/BabylonJS/Babylon.js/blob/9619e67f9d11fa3e5ef4fceaef54e8d1a0eb0000/src/Lights/babylon.directionalLight.ts#L45

 

For point light:https://github.com/BabylonJS/Babylon.js/blob/9619e67f9d11fa3e5ef4fceaef54e8d1a0eb0000/src/Lights/babylon.pointLight.ts#L81

 

Link to comment
Share on other sites

9 hours ago, Deltakosh said:

Interesting concept. I like it a lot. Maybe you should consider integrating in bjs (Need to think how though:))

@nittrus are you using a point light or a directional light? Do you mind creating a PG to repro the issue?

 

If directional light, the cache should be invalidated on every frame: https://github.com/BabylonJS/Babylon.js/blob/2a0c505951937132e926d2375c6ca28d39b19365/src/Lights/Shadows/babylon.shadowGenerator.ts#L393

This is where the matrix is built: https://github.com/BabylonJS/Babylon.js/blob/9619e67f9d11fa3e5ef4fceaef54e8d1a0eb0000/src/Lights/babylon.directionalLight.ts#L45

 

For point light:https://github.com/BabylonJS/Babylon.js/blob/9619e67f9d11fa3e5ef4fceaef54e8d1a0eb0000/src/Lights/babylon.pointLight.ts#L81

 

How does one invalidate the cache of a light?

I also suspect BitofGold is also correct about the shadow map growing to large, is there a way to reduce the shadow map to an area around the character or camera?
It sounded like BitofGold had something that does that but I tried the bit of code and got nothing different, so I was probably doing it wrong.

Is there a way I am supposed to load in that, any special time, like before first render, etc.?

" Do you mind creating a PG to repro the issue? " I may be spacing it or something but what do you mean by PG? I'll probably face palm when you tell me, lol

Link to comment
Share on other sites

I fixed the distortion and direction of shadow issue using:

light.setDirectionToTarget(new BABYLON.Vector3(actor.position.x, actor.position.y-1, actor.position.z));

in the runRenderLoop! The only issue remaining is over comming the fact that the shadow map is fixed position rendering shadows for all objects in the scene.. however, my idea is to add and remove objects using the already made terrain chunk system I created, thus the shadow generator only has a list of currently in view objects as there is no need to have objects out in fog or beyond in the shadow list. I have a good feeling this will work!

Thanks again for the help, I suspect this may be resolved, i'll report back shortly on whether that is the case or not, cheers!

Link to comment
Share on other sites

3 minutes ago, Deltakosh said:

Your idea is the right one: The shadow list has to be dynamic and you already found how to do it :)

 

PG = playground (sorry I write it so many times a day then I'm becoming lazy)

 

Please report back when you have something running. This could help @fluffrabbit to change his mind

Annnddd FACEPALM.. I know PG meant playground.. oi, so much coding leads to brain melt downs, sometimes I'm at it for 14+ hours a day, LOL

I am actually in the process of making the rez/unrez system which I plan to test using an object to load in and unload including the shadow part, shouldn't be to long before I get a proof of concept going.

Cheers!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...