mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 18:29:40 +02:00
84 lines
3.4 KiB
GLSL
84 lines
3.4 KiB
GLSL
// the sun, the moon and the textured sprite of the easter egg, drawn over the sky on a quad around the direction of the body
|
|
// (celestial.vert). param[0]: colour (rgb) and alpha, param[1]: position in view space and half the size of the quad,
|
|
// param[2].xy: corner (sprite) or centre (moon) of the picture in the texture, param[2].z: its size (sprite) or the radius of
|
|
// the disc in it (moon), in texture units, param[2].w: kind of body, 0: textured sprite, 1: sun, 2: moon.
|
|
// the colour goes out premultiplied, the alpha is how much of the sky behind the body it hides (blending ONE, ONE_MINUS_SRC_ALPHA)
|
|
|
|
in vec2 f_coord;
|
|
in vec2 f_local;
|
|
|
|
#texture (tex1, 0, sRGB_A)
|
|
uniform sampler2D tex1;
|
|
|
|
#include <common>
|
|
#include <tonemapping.glsl>
|
|
|
|
// shape and light of the sun and the moon, set by opengl46_renderer::Render(world_environment *):
|
|
// [0].xy: direction to the zenith on the quad, [0].z: height over width of the disc (flattened by the refraction near the
|
|
// horizon), [0].w: radius of the disc in units of half the quad
|
|
// [1].xyz: direction to the sun in view space, [1].w: light of the earth on the dark part of the moon, against the light of
|
|
// the sun on the lit part
|
|
// [2].rgb: limb darkening of the sun per channel (linear law)
|
|
layout(location = 0) uniform vec4 body[3];
|
|
|
|
layout(location = 0) out vec4 out_color;
|
|
#if MOTIONBLUR_ENABLED
|
|
layout(location = 1) out vec4 out_motion;
|
|
#endif
|
|
|
|
void main()
|
|
{
|
|
int kind = int(param[2].w + 0.5);
|
|
vec4 color = vec4(0.0);
|
|
if (kind == 0)
|
|
{
|
|
vec4 tex_color = texture(tex1, f_coord) * param[0];
|
|
color = vec4(tex_color.rgb * tex_color.a, 0.0);
|
|
}
|
|
else
|
|
{
|
|
// the point on the disc in its radii, x along the horizon, y to the zenith, with the flattening undone
|
|
vec2 zenith = body[0].xy;
|
|
vec2 across = vec2(zenith.y, -zenith.x);
|
|
vec2 p = vec2(dot(f_local, across), dot(f_local, zenith)) / body[0].w;
|
|
p.y /= body[0].z;
|
|
float r = length(p);
|
|
float coverage = clamp((1.0 - r) / max(fwidth(r), 1e-4) + 0.5, 0.0, 1.0);
|
|
// the horizon hides what is under it
|
|
vec3 direction = normalize(param[1].xyz + vec3(f_local * param[1].w, 0.0));
|
|
float height = (mat3(inv_view) * direction).y;
|
|
coverage *= clamp(height / max(fwidth(height), 1e-7) + 0.5, 0.0, 1.0);
|
|
// cosine of the angle between the line of sight and the surface of the sphere
|
|
float mu = sqrt(max(1.0 - r * r, 0.0));
|
|
if (kind == 1)
|
|
{
|
|
// limb darkening, kept to the average brightness of the disc
|
|
vec3 limb = (vec3(1.0) - body[2].rgb * (1.0 - mu)) / (vec3(1.0) - body[2].rgb / 3.0);
|
|
color = vec4(param[0].rgb * limb * coverage, 0.0);
|
|
}
|
|
else
|
|
{
|
|
// the moon as a sphere lit from the direction of the sun. the frame of the disc in view space, z to the viewer
|
|
vec3 z = -normalize(param[1].xyz);
|
|
vec3 x = vec3(across, 0.0);
|
|
x = normalize(x - z * dot(x, z));
|
|
vec3 y = cross(z, x);
|
|
vec2 q = p / max(r, 1.0);
|
|
vec3 normal = q.x * x + q.y * y + mu * z;
|
|
float mu0 = max(dot(normal, normalize(body[1].xyz)), 0.0);
|
|
// Lommel-Seeliger law: an even disc at the full moon, as the real one, no darkening towards the limb
|
|
float lit = 2.0 * mu0 / (mu0 + max(mu, 1e-3));
|
|
vec3 albedo = texture(tex1, param[2].xy + p * param[2].z).rgb;
|
|
color = vec4(albedo * param[0].rgb * ((lit + body[1].w) * coverage), coverage * param[0].a);
|
|
}
|
|
}
|
|
#if POSTFX_ENABLED
|
|
out_color = color;
|
|
#else
|
|
out_color = vec4(tonemap(vec4(color.rgb, 1.0)).rgb, color.a);
|
|
#endif
|
|
#if MOTIONBLUR_ENABLED
|
|
out_motion = vec4(0.0f);
|
|
#endif
|
|
}
|