box2dlights icon indicating copy to clipboard operation
box2dlights copied to clipboard

Allow to set the length of shadows

Open haimat opened this issue 10 years ago • 41 comments

Currently in box2dlights a box2d body either casts a shadow or not, there is no in-between. However, in my application I need to specify the length of the shadow for each object, depending on the objects height (in order to simulate a 3d effect).

For example, if the object that would cast the shadow is tall then the shadow is long. But if the object is small, not as tall as the light source height, then the shadow would be shorter.

Would it be hard to implement such a feature in box2dlights?

haimat avatar Dec 28 '14 00:12 haimat

Hi there, thank you for your idea/question.

It's looks like an interesting feature but currently I don't see how it could be implemented, the reason is - for such tall dependent shadow effect the light should be able to acquire from each fixture it's "tall" and currently I don't see where it could be stored, except the user data, which often is used for the different purposes.

Still before any final answer I'll need to check if the ray-casting could handle such cases at all, cause I'm not 100% sure regarding the current implementation.

rinold avatar Dec 29 '14 09:12 rinold

Ohh yes, that indeed sounds like an issue. But is there no attribute within box2d fixtures or bodies (beside the user data), which we could use to store that "height" additional value?

haimat avatar Dec 29 '14 12:12 haimat

I was thinking about that. How about optionally using the user data to store the "tall" value of the object, if you want shadows with different length. In that case you can't use the user data for something else, but since it's optionally you can choose not to use it as well...

haimat avatar Jan 29 '15 15:01 haimat

I also was thinking about that, however it will be a rare case, in most of engines the userData is often used to connect physics body with other engine elements (like graphical objects). But I will try to see what we can do.

rinold avatar Jan 30 '15 08:01 rinold

Thank you very much for your efforts!

haimat avatar Jan 30 '15 11:01 haimat

Hi @haimat,

I have a question - as I understand the "tall" is not enough, we will need a lights "height" position also? Or in your idea of implementation all lights are on the same height?

Also, it's quite hard for me, as I'm not expert, but seems I was able to find some way to do it: image

This is draft implementation of shadows for Directional lights. Will try other light too, but it will be even harder :) Need to find a way to handle ray collision overlapping, e.g. if the light is blocked by fixture, but the fixture next to it is far enough to drop the shadow from this light also... it's a pain my head :) sorry for my english, btw.

rinold avatar Feb 04 '15 10:02 rinold

Wow, that looks already awesome -- great work! Now if you could manage to get that working for point lights too, I would be super happy :-)

To your question: Of course you are right, to be more realistic we would need not only the height of the fixture ("tall"), but also the height of the light source. This would be nice, but having only one value to control the length of the shadow would be better then what we have now.

So in other words: having both, "object height" (tall) and "light height" would be great, but having only "object height" (one valiue) would also be fine!

haimat avatar Feb 04 '15 10:02 haimat

Hi @haimat,

Just interesting, is it possible for you to link not the pre-build jar library but add the box2dlight source project as dependency?

rinold avatar Feb 04 '15 18:02 rinold

You mean for testing your changes? Sure, no problem, I can do that!

haimat avatar Feb 04 '15 19:02 haimat

That would be great! You can use my fork, its could be found by referenced commit above. Current implementation looks good on screenshots, but isn't optimised and I feel its buggy. To use limited height lights you need do 3 things:

  1. Enable experimental mode using rayHandler.setPseudo3dLight(true)
  2. Set fixtures user data to new LightData(height) objects
  3. Set PointLight.setHeight(lightHeight)

And currently it works only for PolygonShape fixtures, tell me what other Shape types you are using to prioritise the implementation for real testing :-)

rinold avatar Feb 04 '15 20:02 rinold

So, I did what you suggested, using your fork and enabling the new pseudo-3d feature. It does work partially: when the fixture is within the point light range, then it seems to work fine. However, when I move the light away from the fixture, then the shadow becomes bright, like light. Hard to explain, so have a look at these screenshots.

This is correct: Good Shadow

And this is wrong: Bad Shadow

haimat avatar Feb 04 '15 21:02 haimat

Oh... could you please share your sample box2dlights setup configuration in your project and sample height values for this issue?

rinold avatar Feb 04 '15 23:02 rinold

fixture.setUserData(new LightData(1.0));

pointLight.setHeight(2.0);
pointLight.setColor(Color.WHITE);
pointLight.setDistance(10.0);  // in my world-dimensions, 1 unit = 64 pixels

RayHandler.setGammaCorrection(false);
rayHandler.useDiffuseLight(true);
rayHandler.setBlurNum(3);
rayHandler.setAmbientLight(0.2, 0.2, 0.2, 1.0);

haimat avatar Feb 04 '15 23:02 haimat

Seems I've messed up some blending and we had different ambient light set. On my (0f, 0f, 0f, 0.5f) this wasn't visible - both blendings gave the same good result. I've pushed the possible fix, give it a try when you have chance! And also, thanks for your time :)

rinold avatar Feb 05 '15 00:02 rinold

Thanks for your last update, it looks already pretty great! There is a bug however -- again, hard to explain. The shadows cast by the polygons now look as if you would look down into an empty cylinder, i.e. as if the polygon was hollow. Additionally, for every polygon I tried in different shapes and with different numbers of vertices the shadow looks as if one side of the polygon would be missing.

With a bit distance the shadow looks good: Good Shadow

Moving the light closer makes the polygon appear hollow: Hollow Polygon

One border/side seems to be missing (not casting any shadow): Side Missing 1

And again: Side Missing 2

But it looks really good already. Seems you are quite close :-)

haimat avatar Feb 05 '15 01:02 haimat

I've tried to do more testing this time :) you can sync with new version and look at it again.

rinold avatar Feb 05 '15 13:02 rinold

Ohh... I've added the userData field to LightData - it solves one general limitation:

    // If it was in your project:
    fixture.setUserData(customData);
    ...
    // Still could be used with modification as:
    fixture.setUserData(new LightData(customData, lightHeight));
    ...
    // And get it back with:
    YourDataType data = (YourDataType) LightData.getUserData(fixture);

So you still could use custom data even with pseudo-3d mode enabled, just adds a bit more pain in getting it later :) Don't know why I haven't thought about it earlier.

rinold avatar Feb 06 '15 14:02 rinold

Hmm, I'm afraid it stills seems a bit buggy. Sometimes (when the light source is in a certain angle to the polygon) a polygon side closer to the light source casts a shadow onto the polygon, that doesn't look right.

Wrong Shadow

haimat avatar Feb 07 '15 17:02 haimat

I've updated code, should fix this issue. Btw, non-convex polygons still are not supported correctly, but should work fine with convex shapes.

rinold avatar Feb 07 '15 19:02 rinold

Thank you very much. It's already looking awesome! There are two things I noticed though:

  1. When the light source is inside the polygon, then the closest side of it does not cast any shadow
  2. It seems to make no difference whether the light source height > polygon fixture height

For the 2nd point I also think the the inside of the poygon should be in shadow if the polygon fixture height is > then the light source height. What do you think about that?

haimat avatar Feb 07 '15 22:02 haimat

I will check the inside case later. For now I've fixed some shadow length computation, and it will be great if you will try following mode:

rayHandler.setPseudo3dLight(true, true);

The second param if true - enables some shadow color interpolation, which looks a bit different - but I don't know which is better :)

Regarding to shadowing the polygon in case of light height < then fixture height sounds reasonably. I will check it also.

rinold avatar Feb 07 '15 23:02 rinold

I have tried the new parameter to interpolate the shadows. It indeed looks smoother = nicer now :-)

haimat avatar Feb 08 '15 03:02 haimat

Hi @haimat,

I've found that current implementation is a bit awful :) it doesn't work for colored lights as usual box2dlight do. I need to re-implement the core, and also due to memory and performance optimization I'm going to move all the code related to this feature to a separate sub-package.

The following development will continue on the libgdx "pseudo3d" branch and I will talk with libgdx team if its possible to move box2dlights nightlies build to this branch also so that you could easily update and test it during development via Gradle and smoothly move onto it when it will be merged to master branch. Also after the first commit to the "pseudo3d" branch it will be better to create issues/enhancements in a separate threads.

P.S. This will take some time, but hope soon you will be able to use it again and it will be event better :) Thanks for your idea and time!

rinold avatar Feb 10 '15 09:02 rinold

Thank you very much for your feedback. So will you answer here in this thread when you have a new version ready for testing, or somewhere else?

haimat avatar Feb 10 '15 09:02 haimat

Yes, I will notify you in this thread :)

rinold avatar Feb 10 '15 09:02 rinold

Hi, have there been further updates regarding the pseudo 3d lights?

jayaxel avatar Mar 20 '15 16:03 jayaxel

I'm quite a busy currently on my job, having a few free time. Even now at holiday I'm writing this from work :) you can check it's current status at box2dlights "pseudo3d" branch, unfortunately there is no built jar could be provided currently, but you can still try it from sources.

rinold avatar Mar 21 '15 12:03 rinold

This should be in Libgdx official release good job guys!

fiz192 avatar May 28 '15 11:05 fiz192

Any plan of a pull request to join it to the master branch? :D

danikaze avatar Oct 24 '15 15:10 danikaze

It might be, but currently the pseudo3d branch is "28 commits behind master" which sounds a bit frightening for the merge :) This will take much work...

rinold avatar Oct 27 '15 09:10 rinold