diff --git a/src/7_planet.fs b/src/7_planet.fs index 075c693..4681e40 100644 --- a/src/7_planet.fs +++ b/src/7_planet.fs @@ -22,6 +22,175 @@ out vec3 color; // perlin_noise, tangent void main() { - color = vec3(0,0,1); -} + const float sun_orbit = 10.0; + const float sun_height = 8.0; + const float sun_frequency = 8.0; + const float epsilon = 0.0001; + const float cloud_scale = 0.9; + const float cloud_intensity = 32.5; + const float cloud_speed = 0.5; + + const float light_intensity = 5.0; + const float twinkle_speed = 0.2; + + /* * * * * * + * Sun * + * * * * * */ + float sun_x = sun_orbit * cos(2.0 * M_PI * animation_seconds / sun_frequency); + float sun_z = sun_orbit * sin(2.0 * M_PI * animation_seconds / sun_frequency); + vec3 sun_pos = (view * vec4(vec3(sun_x, sun_height, sun_z), 1.0)).xyz; + + vec3 light_dir = normalize(sun_pos - view_pos_fs_in.xyz); + vec3 view_dir = normalize(-view_pos_fs_in.xyz); + vec3 normal_dir = normalize(normal_fs_in); + + /* * * * * * * + * Bumps * + * * * * * * */ + vec3 T, B; + tangent(normalize(sphere_fs_in), T, B); + + vec3 normal = cross( + (bump_position(is_moon, sphere_fs_in + epsilon * T) - bump_position(is_moon, sphere_fs_in)) / epsilon, + (bump_position(is_moon, sphere_fs_in + epsilon * B) - bump_position(is_moon, sphere_fs_in)) / epsilon + ); + normal = (view * model(is_moon, animation_seconds) * vec4(normal, 0.0)).xyz; + normal = normalize(normal); + + /* * * * * * * + * Color-pre * + * * * * * * */ + float sun_specular_exponent = 1000.0; + vec3 ka = vec3(0.1, 0.1, 0.1); + vec3 kd; + vec3 ks = vec3(1.0, 1.0, 1.0); + + float bump = bump_height(is_moon, normalize(sphere_fs_in)); + + if (!is_moon) { + /* * * * * * * + * Planet * + * * * * * * */ + + /* Water */ + if (bump < 0.0) { + kd = vec3(0.2, 0.35, 0.8); + sun_specular_exponent = 4000.0; + + float terrain_color = clamp(1 + 15 * bump, 0, 1); /* Still show the depth in the color */ + kd *= terrain_color; + + // Create very small waves, by multiplying the normal with a perlin value + float wave = perlin_noise(sphere_fs_in * 30 + animation_seconds); + wave = pow(wave, 0.1); + wave = 0.1 * smoothstep(0.1, 0.9, wave); + wave = clamp(wave, 0.0, 1.0); + + normal = normal_dir + normal*wave; + normal = normalize(normal); + } + /* Land */ + else { + ks = vec3(0.0, 0.0, 0.0); + kd = vec3(0.2, 0.8, 0.3); + + vec3 beach = vec3(0.9, 0.8, 0.5); + vec3 lush = vec3(0.2, 0.8, 0.3); + vec3 barren = vec3(0.5, 0.5, 0.5); + + if (bump < 0.05) { + kd = mix(beach, lush, smoothstep(0.0, 0.05, bump)); + } else { + kd = mix(lush, barren, smoothstep(0.05, 1.0, bump)); + } + + float terrain_color = clamp(1 + 15 * bump, 0, 1); + kd *= terrain_color; + } + + /* Clouds */ + // Generate clouds, by creating cloud clusters and then filling those clusters with clouds. + vec3 cloud_rotation = vec3(animation_seconds * cloud_speed, 0.0, animation_seconds * cloud_speed); + + float base_cloud = perlin_noise(sphere_fs_in.xyz * 1.3 + cloud_rotation / 5.0); + base_cloud = pow(base_cloud, 1.1); + base_cloud = 100.0 * smoothstep(0.1, 0.9, base_cloud); + base_cloud = clamp(base_cloud, 0.0, 1.0); + + float top_cloud = perlin_noise(sphere_fs_in.xyz * 3.5 + cloud_rotation); + top_cloud = pow(top_cloud, 1.125); + top_cloud = 3.8 * smoothstep(0.1, 0.9, top_cloud); + top_cloud = clamp(top_cloud, 0.0, 1.0); + + /* Combine the base and top cloud */ + float cloud = top_cloud * base_cloud; + + kd = mix(kd, vec3(1.0, 1.0, 1.0), cloud); + kd = clamp(kd, 0.0, 1.0); + + // Modify the normals to make the clouds look fluffy + normal = mix(normal, normal_dir, cloud); + + /* Color */ + color = blinn_phong(ka, kd, ks, sun_specular_exponent, normal, view_dir, light_dir); + + /* Twinking lights */ + float light_factor = dot(normal, light_dir); + if (light_factor < -0.2 && 0.0 < bump) { // Only show the twinkle when the light is coming from the front + vec3 twinkle_vector = vec3(animation_seconds * twinkle_speed, 0.0, animation_seconds * twinkle_speed); + float twinkle_pos = perlin_noise(sphere_fs_in * 100 + twinkle_vector); + twinkle_pos = pow(twinkle_pos, 1.35); + float twinkle_intensity = perlin_noise(sphere_fs_in * 0.5 * twinkle_vector); + twinkle_pos = twinkle_intensity * 100.0 * smoothstep(0.3, 1.0, twinkle_pos); + twinkle_pos = clamp(twinkle_pos, 0.0, 1.0); + + // RGB LIGHTS! (Groetjes aan Julie) + float r_mix = perlin_noise(sphere_fs_in * twinkle_vector * animation_seconds + 1.0); + r_mix = 1000 * smoothstep(0.01, 0.95, r_mix); + r_mix = clamp(r_mix, 0.0, 1.0); + float g_mix = perlin_noise(sphere_fs_in * twinkle_vector * animation_seconds + 2.0); + g_mix = 1000 * smoothstep(0.01, 0.95, g_mix); + g_mix = clamp(g_mix, 0.0, 1.0); + float b_mix = perlin_noise(sphere_fs_in * twinkle_vector * animation_seconds + 3.0); + b_mix = 1000 * smoothstep(0.01, 0.95, b_mix); + b_mix = clamp(b_mix, 0.0, 1.0); + + vec3 twinkle_color = vec3(r_mix, g_mix, b_mix); + vec3 final_twinkle_color = mix(vec3(1.0, 1.0, 1.0), twinkle_color, r_mix); + + color = mix(color, final_twinkle_color, twinkle_pos); + color = clamp(color, 0.0, 1.0); + } + } else { + /* * * * * * * + * Moon * + * * * * * * */ + + kd = vec3(0.2, 0.2, 0.2); + sun_specular_exponent = 500.0; + ks = vec3(0.1, 0.1, 0.1); + + /* Charcoal color */ + float charcoal = perlin_noise(sphere_fs_in.xyz * 2.3); + charcoal = pow(charcoal, 0.3); + charcoal = 1.1 * smoothstep(0.1, 0.9, charcoal); + charcoal = clamp(charcoal, 0.0, 1.0); + + kd = mix(kd, vec3(1.0, 0.0, 0.0), 1.0 - charcoal); + + // Smoothen the bumped normal + normal = mix(normal, normal_dir, 1 - charcoal); + + /* Color */ + color = blinn_phong(ka, kd, ks, sun_specular_exponent, normal, view_dir, light_dir); + + /* Charcoal glow */ + color = mix(color, kd, 1.0 - charcoal); + float glow_intensity = perlin_noise(vec3(0.25 * animation_seconds)); + glow_intensity = pow(glow_intensity, 0.3); + glow_intensity = 1.1 * smoothstep(0.1, 0.9, glow_intensity); + glow_intensity = clamp(glow_intensity, 0.2, 1.0); + color *= glow_intensity; + } +}