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);
}



