Skip to content
Antonio Caggiano edited this page Oct 19, 2021 · 1 revision

To render the sky we use a custom shader. This step is optional and can be enabled by setting spot.gfx.renderer.sky.enabled as true. It consists of just another quad primitive being drawn in front of the main camera so to occupy the whole screen. Then the actual colors of the primitive's fragments are calculated in the fragment shader.

The main thing to consider is that the sky can have two color values, one at the horizon and another at the zenit. Between the horizon and the zenit we can see a smooth transition between the corresponding colors. This takes into account the angle between the fragment position in world space and the horizontal plane. The lesser is the angle, the closer the resulting color will be to the horizon color, while the greater is the angle, the closer the resulting color will be to the zenit color.

This effect can be achieved by means of the mix() function.

vec3 color = mix(horizon, zenit, mix_factor);

The value used as mix_factor should be comprised between 0.0 and 1.0. Since it should be related to the angle aforementioned, we can use the dot product between the fragment position and its projection onto the horizontal plane. When the position along the Y axis is negative, we will just pick 0.0 as mix_factor.

vec3 pos = normalize(position);
vec3 pos_proj = normalize(vec3(pos.x, 0.0, pos.z));
float sig = pos.y / abs(pos.y);
float mix_factor = max(0.0, sig * (1.0 - dot(pos, pos_proj)));

Fragment position in world space

While the geometry just needs to cover the entire screen and have depth equal to 1.0 so to appear behind anything else, the fragment position in world space is a complete different thing. The idea is to look at a unit sphere from its center, so as the camera rotates the fragment position rotates accordingly. This is achieved by shifting the position along -Z (forward in OpenGL) and applying to it the camera rotation, ignoring its translation.

vec3 position = mat3(camera_model) * vec3(in_pos.xy, -1.0);
Clone this wiki locally