Light scattering [SOLVED]

Hey all,

While testing light scattering

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestLightScattering.java

I noticed a rather strange behavior when camera turns away from the light source. You can notice in the following movie that when turning to the left side of the camera it goes smoothly, the pass from the god rays area to an area wo the effect goes gradual. To right side of the camera however, the pass is very sudden. It seems the color of the skybox, not the sun, so blueish is scattered almost to opacity, maximum is when the actual lightsource is in the left bottom corner of the screen.

Anyone has an idea about the cause and possible fixes?

Thanks in advance,

Florin

LE: changing the skybox with a darker one, turns into disaster, the scattered color of the skybox is darkening the viewport completely when the actual light source is in bottom left corner. The other direction or looking straight to the lightsource, works fine, no problem.

2 Likes

One more thing, it seems the effect itself is at maximum intensity when the light position is translated to screen coordinates 0,0 - lower left corner, not the center of the screen. I think thats related to the issue above. Ill investigate more in the code…

Sorry i didn’t see this post before.

Actually that’s a feature. The light scattering is stopped when the light source goes out of the camera view for several reasons :

  • It somehow fits the actual physical effect (not completely true because you can see scattering when you have some fog or things like that, but here it’s more like light streaks).
  • It’s very expensive, so stopping it when it’s not relevant looked like the appropriate choice.
  • And above all…it looks awful when the light is not in the camera view (that’s more of an implementation issue).



    You can remove this behavior by replacing lie 108 of the filter by :

    [java]

    display = true;

    [/java]

Hey @nehon,



No problem with removing when off camera. The problem is that the scattering is not symmetric to the center of the screen, as I said, the maximum strength is when in lower left corner of the display, thus leading to the fact that the removing when turning to right, is much more obvious than removing when turning left…

Yeah the attenuation code, is quick and dirty really…I guess now it’s just dirty :stuck_out_tongue:



I committed a change that should alleviate the issue. Could you try?

1 Like

Thanks @nehon, I’ll confirm as soon as I get nightlies to work :slight_smile:

Sorry to get back on this so late.
It doesn’t seem to be changed in any way. Still the maximum strength of the effect is with the “sun” position in low left corner…

Are you using nightly?
just to be sure.

Version: 3.0.0.10219 Source: jMonkeyEngine SDK Nightly (Breaks!)

LE: 233 now, still the same…

@fbucur said: Sorry to get back on this so late. It doesn't seem to be changed in any way. Still the maximum strength of the effect is with the "sun" position in low left corner...

Are you sure that’s not just the sky image used? Since it scatters the color from the rendered scene if there is something really dark there then it will scatter more apparently than other directions.

Maybe you can try an all white and then an all black sky box to see or something (obviously with some other things in the scene).

I did try with the scattering example
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestLightScattering.java
as you can see in the video

whatever the color of the sky image is, thats the color that fills the screen when the light source is in lower left corner…

OK , i changed the way it’s phased out, should be better now.

sorry to be such a pain in the back, its still the same as behavior, meaning, the phase out is not the same if you move the camera to the right of the light source or to the left.
also, the maximum intensity of the effect is still in the lower left corner of the screen (0,0) not in the center (width/2, height/2) and i think thats what causes the difference in phasing out by direction left or right. i tried to play with the filter but no luck in changing the maximum point of intensity from lowleft to center of the screen. ill keep trying…

Well i don’t get what you mean, for me it looks ok.
I fixed the issues demonstrated in the previous video. If you have another issue, maybe make another video, because i don’t get it.

@fbucur I had the same issue. The code for adaptive didn’t seem quite right. The scatter intensity was very high when the light source was in the lower left hand corner, but was weak in the top/left, top/right, bottom/right. I also saw the “snapping” when the light source came out of view from the left side. I came up with a few alternatives. The first one keeps the intensity quite high until the light source leaves the screen. The second approach is more subtle. I ended up creating a scattering filter (based on the stock one) that has a toggle for the “high gain” method (#1).

I was able to fix this by effectively overriding postQueue()

Original LightScatteringFilter line 105:
[java]
innerLightDensity = Math.max(lightDensity - Math.max(screenLightPos.x, screenLightPos.y), 0.0f);
[/java]

Mine #1:
Note: You’ll need to add private Vector3f lightDirectionStore and camDirectionStore.
[java]
viewPort.getCamera().getDirection(camDirectionStore);
lightDirectionStore.set(lightPosition);
lightDirectionStore.subtractLocal(viewPort.getCamera().getLocation()).normalizeLocal();
float angle = camDirectionStore.angleBetween(lightDirectionStore);
float densityX = 1 - FastMath.clamp(FastMath.abs(screenLightPos.x - 0.5f), 0, 1);
float densityY = 1 - FastMath.clamp(FastMath.abs(screenLightPos.y - 0.5f), 0, 1);
innerLightDensity = lightDensity * Math.max(densityX, densityY) * FastMath.cos(angle);
[/java]

Mine #2
[java]
float densityX = 1 - FastMath.clamp(FastMath.abs(screenLightPos.x - 0.5f), 0, 1);
float densityY = 1 - FastMath.clamp(FastMath.abs(screenLightPos.y - 0.5f), 0, 1);
innerLightDensity = lightDensity * densityX * densityY;
[/java]

Also, I noticed that “adaptative” (i assume this is supposed to be adaptive) doesn’t have a getter/setter pair.

Now, for my question!

@nehon Is there any way to prevent the light scattering from using the skybox as part of the input texture? When the skybox consists of clouds it makes sense to use the sky texture, as the clouds appear to sit between the camera and the light (sun) and you get nice rays of light emitting from the lighter spots. The issue I’m having is that my scene is in space and I don’t want the rays of light to be emitting from the background stars.

I’m usuing bloom + light scattering to create a nice warm looking sun. I’d like to have the scattering of the bloom and light source effectively rendered “on top of” the skybox.

2 Likes

Cool, I’ll look if i can integrate your changes.

to answer your question, I’d like the light scattering to work on an arbitrary object, or even a light source… Right now it only work on the skybox really and there is no way around it.
it’s been a long time since i didn’t look at the code this filter could use a brush up I guess.

Thank you @aaron! This “simple” fix is surprisingly effective. @nehon I really think this should be integrated into your version, it really fixes opacity snapping problems when we turn the camera to the right. It really smooths out the filter’s opacity transitions altogether.

I think I did…but i’ll check that out :stuck_out_tongue:

I just want to post here that I had to adjust 2 lines tough to get a perfect saturation, altough it may only be specific to my implementation, but if you see distorted over saturated colors when aiming at the sun, simply change these 2 lines: (around lines 113-114)

[java]
float densityX = 1 - FastMath.clamp(FastMath.abs(screenLightPos.x - 0.5f), 0, 1);
float densityY = 1 - FastMath.clamp(FastMath.abs(screenLightPos.y - 0.5f), 0, 1);
[/java]

…for these 2 lines:

[java]
float densityX = 0.5f - FastMath.clamp(FastMath.abs(screenLightPos.x - 0.5f), 0, 1);
float densityY = 0.5f - FastMath.clamp(FastMath.abs(screenLightPos.y - 0.5f), 0, 1);
[/java]

And @nehon, you can’t possibly have integrated this already, because your Google Code dates back to October 2012 and that’s what I got in the first place, 1 month ago. I couldn’t find anything newer anywhere online :stuck_out_tongue: But maybe I looked at the wrong place? This is the most recent I could find: code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/post/TestLightScattering.java

Thx :smiley: