Orbiting Planet with Moon

A customizable planet shader.

Apply the shader to a ColorRect.

The planet orbits the center of the center of the ColorRect.

Settings for : Planet and Moon Orbit,Planet Appearance, Moon Appearance, Atmosphere Effects and Orbiting Body Size.

Shader code
//Custom Planet Shader
shader_type canvas_item;


group_uniforms planet_and_moon_orbit;
uniform float planet_orbit_speed : hint_range(0.001, 2.0) = 0.2;
uniform float planet_orbit_h : hint_range(0.1, 1.0) = 0.4;
uniform float planet_orbit_v : hint_range(0.0, 0.5) = 0.1;

uniform float moon_orbit_speed : hint_range(-5.0, 5.0) = 1.5;
uniform float moon_orbit_h : hint_range(0.01, 0.2) = 0.1;
uniform float moon_orbit_v : hint_range(0.0, 0.1) = 0.03;

group_uniforms planet_appearance;
uniform float planet_size : hint_range(0.001, 0.1) = 0.02;
uniform float perspective_scale_amount : hint_range(0.0, 1.0) = 0.3;
uniform vec4 crack_color : source_color = vec4(1.0, 0.8, 0.5, 1.0);
uniform vec4 magma_color : source_color = vec4(0.8, 0.4, 0.1, 1.0);
uniform vec4 crust_color : source_color = vec4(0.2, 0.05, 0.0, 1.0);
uniform float magma_complexity : hint_range(1.0, 10.0) = 5.0;
uniform float magma_flow_speed : hint_range(0.1, 2.0) = 0.3;

group_uniforms Moon_Appearance;
uniform float moon_size : hint_range(0.001, 0.02) = 0.005;
uniform vec4 moon_light_color : source_color = vec4(0.9, 0.9, 1.0, 1.0);
uniform vec4 moon_dark_color : source_color = vec4(0.3, 0.3, 0.4, 1.0);
uniform float moon_crater_complexity : hint_range(1.0, 20.0) = 12.0;

group_uniforms Atmosphere_Effects;
uniform vec4 atmosphere_color : source_color = vec4(1.0, 0.5, 0.2, 1.0);
uniform float atmosphere_thickness : hint_range(0.0, 0.5) = 0.2;

uniform float rim_glow_intensity : hint_range(0.0, 10.0) = 4.0;
uniform float crescent_bias_near : hint_range(-1.0, 1.0) = -0.9;
uniform float crescent_bias_far : hint_range(-1.0, 1.0) = 0.2;
uniform float atmosphere_glow_intensity : hint_range(0.0, 10.0) = 3.0;

group_uniforms Core_Size;
uniform float orbiting_body_size : hint_range(0.0, 0.5) = 0.1;
uniform float orbiting_body_thickness : hint_range(0.0, 0.2) = 0.05;

float random(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453); }
float noise(vec2 st) {
    vec2 i = floor(st); vec2 f = fract(st);
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(mix(random(i), random(i + vec2(1.0, 0.0)), u.x),
               mix(random(i + vec2(0.0, 1.0)), random(i + vec2(1.0, 1.0)), u.x), u.y);
}
float fbm_noise(vec2 uv, vec2 time_vec, int octaves) {
    float value = 0.0; float amplitude = 0.5;
    for (int i = 0; i < octaves; i++) {
        value += noise(uv + time_vec) * amplitude;
        uv *= 2.0; amplitude *= 0.5;
    } return value;
}

void fragment() {
    //  1. Calculate Orbits & Perspective
    float planet_angle = TIME * planet_orbit_speed;
    vec2 planet_pos = vec2(cos(planet_angle) * planet_orbit_h, sin(planet_angle) * planet_orbit_v);
    float planet_perspective = sin(planet_angle);
    float planet_scale = 1.0 + planet_perspective * perspective_scale_amount;
    float planet_radius = planet_size * planet_scale;

    float moon_angle = TIME * moon_orbit_speed;
    vec2 moon_local_pos = vec2(cos(moon_angle) * moon_orbit_h, sin(moon_angle) * moon_orbit_v);
    vec2 moon_pos = planet_pos + moon_local_pos * planet_scale;
    float moon_perspective = sin(moon_angle);
    float moon_radius = moon_size * planet_scale;

    //  2. Create Surfaces
    vec2 centered_uv = UV - vec2(0.5);
    float dist_from_planet = distance(centered_uv, planet_pos);
    float planet_mask = smoothstep(planet_radius, planet_radius - 0.005, dist_from_planet);
    vec2 planet_surface_uv = (centered_uv - planet_pos) / planet_radius;
    
    vec2 time_magma = vec2(TIME * magma_flow_speed * 0.1, 0.0);
    vec2 time_crust = vec2(0.0, TIME * magma_flow_speed * 0.02);
    float magma_noise = fbm_noise(planet_surface_uv * magma_complexity, time_magma, 6);
    float crust_noise = fbm_noise(planet_surface_uv * magma_complexity * 0.5, time_crust, 6);
    float crust_mask = smoothstep(0.4, 0.6, crust_noise);
    float cracks = pow(1.0 - crust_noise, 5.0) * 0.5;
    vec3 planet_surface_color = mix(magma_color.rgb * magma_noise, crust_color.rgb, crust_mask) + cracks * crack_color.rgb;

    float dist_from_moon = distance(centered_uv, moon_pos);
    float moon_mask = smoothstep(moon_radius, moon_radius - 0.005, dist_from_moon);
    vec2 moon_surface_uv = (centered_uv - moon_pos) / moon_radius;
    float crater_noise = fbm_noise(moon_surface_uv * moon_crater_complexity, vec2(0.0), 4) * 0.5 + 0.5;
    vec3 moon_surface_color = mix(moon_dark_color.rgb, moon_light_color.rgb, crater_noise);

    //  3. lighting model
    vec3 lit_planet_surface = vec3(0.0);
    float planet_diffuse = 0.0;
    float planet_rim_glow = 0.0;
    if (dot(planet_surface_uv, planet_surface_uv) <= 1.0) {
        float z = sqrt(1.0 - dot(planet_surface_uv, planet_surface_uv));
        vec3 normal = vec3(planet_surface_uv, z);
        vec3 light_dir = normalize(vec3(-planet_pos, 0.25));
        float phase_factor = (planet_perspective + 1.0) * 0.5;
        float auto_bias = mix(crescent_bias_far, crescent_bias_near, phase_factor);
        planet_diffuse = max(0.0, dot(normal, light_dir) + auto_bias);
		
        float rim = pow(1.0 - abs(dot(normal, vec3(0.0, 0.0, 1.0))), 4.0);
        float transit_factor = smoothstep(0.0, 0.8, planet_perspective); // 1.0 when close, 0.0 when far
        planet_rim_glow = rim * transit_factor * rim_glow_intensity * max(0.0, dot(normal, light_dir));
        lit_planet_surface = planet_surface_color * planet_diffuse + (crack_color.rgb * planet_rim_glow);
    }

    //  4. Moon and Shadow Lighting
    vec3 lit_moon_surface = vec3(0.0);
    if (dot(moon_surface_uv, moon_surface_uv) <= 1.0) {
        float moon_z = sqrt(1.0 - dot(moon_surface_uv, moon_surface_uv));
        vec3 moon_normal = vec3(moon_surface_uv, moon_z);
        vec3 moon_light_dir = normalize(vec3(-moon_pos, 0.25));
        float moon_diffuse = max(0.0, dot(moon_normal, moon_light_dir));
        lit_moon_surface = moon_surface_color * moon_diffuse;
        
        vec2 shadow_dir = normalize(planet_pos);
        float projection = dot(moon_pos, shadow_dir);
        float dist_from_shadow_center = length(moon_pos - projection * shadow_dir);
        float is_behind = smoothstep(length(planet_pos), length(planet_pos) + 0.01, projection);
        float shadow_penumbra = 1.0 - smoothstep(planet_radius, planet_radius + moon_radius, dist_from_shadow_center);
        float shadow_strength = shadow_penumbra * is_behind;
        lit_moon_surface *= (1.0 - shadow_strength);
    }
    
    //  5. atmosphere
    float atmosphere_radius = planet_radius * (1.0 + atmosphere_thickness);
    float atmosphere_mask = 1.0 - smoothstep(planet_radius, atmosphere_radius, dist_from_planet);
    
    float day_haze = planet_diffuse * 0.3;
    float eclipse_glow = planet_rim_glow * atmosphere_glow_intensity;
    
    vec3 lit_atmosphere_color = atmosphere_color.rgb * (day_haze + eclipse_glow);
    
    //  6. Final Composition 
    vec3 final_rgb = lit_atmosphere_color * atmosphere_mask;
    if (moon_perspective > 0.0) {
        final_rgb = mix(final_rgb, lit_planet_surface, planet_mask);
        final_rgb = mix(final_rgb, lit_moon_surface, moon_mask);
    } else {
        final_rgb = mix(final_rgb, lit_moon_surface, moon_mask);
        final_rgb = mix(final_rgb, lit_planet_surface, planet_mask);
    }
    
    //  7. Occlusion 
    float dist_from_screen_center = length(planet_pos);
    float eclipse_corona_radius = orbiting_body_size + orbiting_body_thickness;
    float occlusion_fade = 1.0;
    if (planet_perspective < 0.0) {
        occlusion_fade = smoothstep(eclipse_corona_radius - 0.01, eclipse_corona_radius + 0.01, dist_from_screen_center);
    }
    
    float final_alpha = max(max(planet_mask, moon_mask), atmosphere_mask) * occlusion_fade;
    COLOR = vec4(final_rgb, final_alpha);
}
Tags
moon, Orbit, planet, space
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Sea and Moon

Moon Phase

Moon Shader 2D All Phases and Roughened Shadow

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments