SkyControl + WaterFilter + large scene = I need help

I’m using the SkyControl plugin, which looks incredible by the way, to add day-night cycles to a project I’m working on. The project has a rather large island, and I’m using WaterFilter for the water. If you go to the highest point on the mountain and look off into the distance, you can see where the sky sphere is by the reflection in the water. Instead of reflecting it as a far-off skybox, it reflects as if it’s a sphere sitting on top of the water. I realize that this is because that’s all it is - a sphere - but I was wondering if there was a fix or a workaround for this. One thing to note is that if I use SkyFactory, it looks fine, but I lose the dynamic sky and such. Things I’ve tried:
-Extending the SkyControl class, and:
–for each geometry of the sky, scaling it up (resulted in a crash)
–for each geometry of the sky, set its model bound to a BoundingSphere with a radius of the max float value (no difference)
–for each geometry of the sky, set its queue bucket to sky (I figured it already was but I tried anyway, no difference)

Idk how the sky control works, but, you could try to place the sky sphere in the sky bucket

@nehon I tried that. That was one of the first things I tried, and it didn’t appear to change anything. I can’t really think of anything that could be causing this. I looked at how SkyFactory creates the sky, and it just uses a Sphere with a radius of 10, and with a BoundingSphere whose radius is Float.POSITIVE_INFINITY. I’ve more or less done the exact same thing and the problem persists.

Can you show us a picture of what you mean? I’m not sure from the description and a picture is worth several hundred thousand words in cases like this.

could you post a screenshot of the issue?

@pspeed I suppose I should’ve done that before, here it is:

You can see where the Sky Sphere is, rather than it appearing to be the actual sky in the reflection.

Another interesting thing to note is that if I fly high enough up, I fly >out< of the Sky Sphere (at least that’s what appears to be happening because of the reflection). At that point, I see this:

I have no idea what to think here.

The only thing being correctly reflected is the stars. Other than that it’s reflecting the Sphere rather than treating it like an environment.

I could be guessing here but I’ve had similar issues with my own classes and I end up doing things a different way.

One problem with skies is that they need to stay with the camera as you move around. A way to handle this is to just move the sky to the camera’s location every frame. JME doesn’t provide a way to have a ‘null’ or view-relative transform in this sense (unfortunate, too).

So if that’s all true in this case then the issue is that the reflection of the water is using a different camera and so the sky will not be centered around that camera.

My sky from Sim-FX (open source lib in my simsilica-tools stuff) gets around this by ignoring the view transform in the shader itself… so it’s correct for all cameras.

@pspeed How would I go about modifying the shader to make that so? I’m assuming there’s something I would change in the vertex shader to ignore the transform?

SkyControl was designed to cooperate with SimpleWaterFilter. This is demonstrated in the TestSkyControl demo application. The trick was to inform SkyControl (or to be precise, its updater) about the preview viewports created by SimpleWaterFilter.

I’ve not used any other water filters, so I can’t say if the same trick will work with com.jme3.water.WaterFilter (assuming that’s what you’re using).

1 Like
@vinexgames said: @pspeed How would I go about modifying the shader to make that so? I'm assuming there's something I would change in the vertex shader to ignore the transform?

The vertex shader probably has a line like:
gl_Position = g_WorldViewProjectionMatrix * modelPos;
…or something like that.

modelPos is often vec4(inPos, 1.0)

You want to only apply view rotation so instead you want vec4(inPos, 0.0) and only against the view ie:
gl_Position = g_ViewProjectionMatrix * vec4(inPos, 0.0);

…though it’s possible that you have to split view and projection into two separate calls. My sky shader does:
vec4 temp = g_ViewMatrix * vec4(inPosition, 0.0);
temp.w = 1.0;
gl_Position = g_ProjectionMatrix * temp;

At the bottom of:

To me that’s easier than trying to manage x number of reflection cameras.

1 Like