Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save RemyCampanals/044fe42ed5c336780d21bc77ca67c0ac to your computer and use it in GitHub Desktop.
Save RemyCampanals/044fe42ed5c336780d21bc77ca67c0ac to your computer and use it in GitHub Desktop.
Sky.gd for Godot 4.0
@tool
extends Node3D
@onready var env: Environment = $WorldEnvironment.environment;
@onready var sun: Node3D = $Sun_Moon;
# Sky
@onready var sky_view: SubViewport = $sky_viewport;
@onready var sky_tex: Sprite2D = $sky_viewport/sky_texture;
# Clouds
@onready var clouds_view: SubViewport = $clouds_viewport;
@onready var clouds_tex: Sprite2D = $clouds_viewport/clouds_texture;
var time_of_day: float = 0.0;
var one_second: float = 1.0 / (24.0 * 60.0 * 60.0);
# setget | Sky & Clouds
@export var clouds_resolution: int = 1024:
get:
return clouds_resolution;
set(value):
clouds_resolution = value;
if is_inside_tree():
print('yes clouds');
clouds_view.size = Vector2(clouds_resolution,clouds_resolution);
clouds_tex.texture.set_size_override(Vector2(clouds_resolution,clouds_resolution));
@export var sky_resolution: int = 2048:
get:
return sky_resolution;
set(value):
sky_resolution = value;
if is_inside_tree():
sky_view.size = Vector2(sky_resolution,sky_resolution);
sky_tex.texture.set_size_override(Vector2(sky_resolution,sky_resolution));
@export var sky_gradient_texture: GradientTexture2D:
get:
return sky_gradient_texture;
set(value):
sky_gradient_texture = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sky_gradient_texture",sky_gradient_texture);
@export var SCATERRING: bool = false:
get:
return SCATERRING;
set(value):
SCATERRING = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/SCATERRING",SCATERRING);
@export var color_sky: Color = Color(0.25,0.5,1.0,1.0):
get:
return color_sky;
set(value):
color_sky = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/color_sky",color_sky);
@export var sky_tone: float = 3.0:
get:
return sky_tone;
set(value):
sky_tone = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sky_tone",sky_tone);
@export var sky_density: float = 0.75:
get:
return sky_density;
set(value):
sky_density = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sky_density",sky_density);
@export var sky_rayleig_coeff: float = 0.75:
get:
return sky_rayleig_coeff;
set(value):
sky_rayleig_coeff = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sky_rayleig_coeff",sky_rayleig_coeff);
@export var sky_mie_coeff: float = 2.0:
get:
return sky_mie_coeff;
set(value):
sky_mie_coeff = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sky_mie_coeff",sky_mie_coeff);
@export var multiScatterPhase: float = 0.0:
get:
return multiScatterPhase;
set(value):
multiScatterPhase = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/multiScatterPhase",multiScatterPhase);
@export var anisotropicIntensity: float = 0.0:
get:
return anisotropicIntensity;
set(value):
anisotropicIntensity = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/anisotropicIntensity",anisotropicIntensity);
@export var time_of_day_setup: float = 0.0:
get:
return time_of_day_setup;
set(value):
time_of_day_setup = clamp(value, 0, 1.0);
set_time_of_day(time_of_day_setup);
@export var hours: int = 0:
get:
return hours;
set(value):
hours = clamp(value, 0, 23);
#set_time_of_day((hours * 3600 + minutes * 60 + seconds) * one_second);
@export var minutes: int = 0:
get:
return minutes;
set(value):
minutes = clamp(value, 0, 59);
#set_time_of_day((hours * 3600 + minutes * 60 + seconds) * one_second);
@export var seconds: int = 0:
get:
return seconds;
set(value):
seconds = clamp(value, 0, 59);
#set_time_of_day((hours * 3600 + minutes * 60 + seconds) * one_second);
@export var clouds_coverage: float = 0.5:
get:
return clouds_coverage;
set(value):
clouds_coverage = clamp(value, 0.0, 1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/ABSORPTION",clouds_coverage+0.75);
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/COVERAGE",1.0-(clouds_coverage*0.7+0.1));
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/THICKNESS",clouds_coverage*10.0+10.0);
call_deferred("set_time");
@export var clouds_size: float = 2.0:
get:
return clouds_size;
set(value):
clouds_size = clamp(value, 0.0, 10.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/SIZE",clouds_size);
@export var clouds_softness: float = 1.0:
get:
return clouds_softness;
set(value):
clouds_softness = clamp(value,0.0,10.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/SOFTNESS",clouds_softness);
@export var clouds_dens: float = 0.07:
get:
return clouds_dens;
set(value):
clouds_dens = clamp(value,0.0,1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/DENS", clouds_dens);
@export var clouds_height: float = 0.35:
get:
return clouds_height;
set(value):
clouds_height = clamp(value,0.0,1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/HEIGHT", clouds_height);
@export var clouds_quality: int = 25:
get:
return clouds_quality;
set(value):
clouds_quality = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/STEPS",clamp (clouds_quality,5,100));
@export var clouds_tint: Color = Color(1.0,1.0,1.0,1.0):
get:
return clouds_tint;
set(value):
clouds_tint = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/clouds_tint", clouds_tint);
@export var wind_dir: Vector2 = Vector2(1.0,0.0):
get:
return wind_dir;
set(value):
wind_dir = value.normalized();
set_wind_strength(wind_strength);
@export var wind_strength: float = 0.1:
get:
return wind_strength;
set(value):
wind_strength = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/WIND",Vector3(wind_dir.x,0.0,wind_dir.y)*wind_strength);
var sun_pos: Vector3;
var moon_pos: Vector3;
var god_rays;
var iTime: float = 0.0;
@export var moon_light: Color = Color(0.6,0.6,0.8,1.0);
@export var sunset_light: Color = Color(1.0,0.7,0.55,1.0);
@export var day_light: Color = Color(1.0,1.0,1.0,1.0);
@export var sunset_offset: float = -0.1;
@export var sunset_range: float = 0.2;
# setget | Sun & Moon
@export var moon_tint: Color = Color(1.0,0.7,0.35,1.0):
get:
return moon_tint;
set(value):
moon_tint = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/moon_tint", moon_tint);
@export var sun_radius: float = 0.04:
get:
return sun_radius;
set(value):
sun_radius = clamp(value,0.0,1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/sun_radius", sun_radius);
@export var moon_radius: float = 0.1:
get:
return moon_radius;
set(value):
moon_radius = clamp(value,0.0,1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/moon_radius", moon_radius);
@export var moon_phase: float = 0.0:
get:
return moon_phase;
set(value):
moon_phase = clamp(value,-1.0,1.0);
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/MOON_PHASE", moon_phase);
@export var night_level_light: float=0.05:
get:
return night_level_light;
set(value):
night_level_light = clamp(value, 0.0, 1.0);
set_time();
@export var lighting_pos: Vector3 = Vector3(0.0,1.0,1.0):
get:
return lighting_pos;
set(value):
lighting_pos = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/LIGHTTING_POS",lighting_pos.normalized());
func set_sky_resolution(value: int):
sky_resolution = value
if is_inside_tree():
sky_view.size = Vector2(sky_resolution,sky_resolution)
sky_tex.texture.set_size_override(Vector2(sky_resolution,sky_resolution))
func _ready():
god_rays = get_node_or_null("GodRays")
_set_god_rays(false)
set_lighting_strike(false)
set_time();
func reflections_update():
env.sky.sky_material.panorama = sky_view.get_texture();
func set_time():
if !is_inside_tree():
return;
var light_color :Color = Color(1.0,1.0,1.0,1.0)
var phi: float = time_of_day*2.0*PI
sun_pos = Vector3(0.0,-1.0,0.0).normalized().rotated(Vector3(1.0,0.0,0.0).normalized(),phi) #here you can change the start position of the Sun and axis of rotation
moon_pos = Vector3(0.0,1.0,0.0).normalized().rotated(Vector3(1.0,0.0,0.0).normalized(),phi) #Same for Moon
var moon_tex_pos: Vector3 = Vector3(0.0,1.0,0.0).normalized().rotated(Vector3(1.0,0.0,0.0).normalized(),(phi+PI)*0.5) #This magical formula for shader
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/MOON_TEX_POS",moon_tex_pos)
var light_energy: float = smoothstep(sunset_offset,0.4,sun_pos.y);# light intensity depending on the height of the sun
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/SUN_POS",sun_pos)
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/MOON_POS",moon_pos)
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/SUN_POS",-sun_pos)
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/attenuation",clamp(light_energy,night_level_light*0.25,1.00))#clouds to bright with night_level_light
light_energy = clamp(light_energy,night_level_light,1.00);
var sun_height: float = sun_pos.y-sunset_offset
if sun_height < sunset_range:
light_color = hsv_lerp(moon_light, sunset_light, clamp(sun_height/sunset_range,0.0,1.0))
else:
light_color = hsv_lerp(sunset_light, day_light, clamp((sun_height-sunset_range)/sunset_range,0.0,1.0))
if sun_pos.y < 0.0:
if moon_pos.normalized() != Vector3.UP:# error Up vector and direction between node origin and target are aligned, look_at() failed.
sun.look_at_from_position(moon_pos,Vector3.ZERO,Vector3.UP); # move sun to position and look at center scene from position
else:
if sun_pos.normalized() != Vector3.UP:
sun.look_at_from_position(sun_pos,Vector3.ZERO,Vector3.UP); # move sun to position and look at center scene from position
set_clouds_tint(light_color) # comment this, if you need custom clouds tint
light_energy = light_energy *(1-clouds_coverage*0.5)
sun.light_energy = light_energy
sun.light_color = light_color
env.ambient_light_energy = light_energy
env.ambient_light_color = light_color
env.adjustment_saturation = 1-clouds_coverage*0.5
env.fog_light_color = light_color;
#call_deferred("reflections_update");
func set_time_of_day(value: float):
var time: float = value/one_second
value -= 2.0/24.0;
if value < 0.0:
value = 1.0 + value;
var _time_of_day = value;
hours = int(clamp(time/3600.0,0.0,23.0));
time -= hours*3600
minutes = int(clamp(time/60,0.0,59.0));
time -= minutes*60
seconds = int(clamp(time,0.0,59.0));
set_time();
func _process(delta):
iTime += delta
var lighting_strength = clamp(sin(iTime*20.0),0.0,1.0)
lighting_pos = lighting_pos.normalized()
sun.light_color = day_light
sun.light_energy = lighting_strength*2
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/LIGHTTING_POS",lighting_pos)
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/LIGHTING_STRENGTH",Vector3(lighting_strength,lighting_strength,lighting_strength))
sun.look_at_from_position(lighting_pos,Vector3.ZERO,Vector3.UP);
clouds_tex.texture = clouds_view.get_texture();
func set_sun_position():
lighting_pos = lighting_pos.normalized();
sun.look_at_from_position(lighting_pos,Vector3.ZERO,Vector3.UP);
func set_lighting_strike(on: bool):
if on:
_set_god_rays(false)
set_process(true)
else:
_set_god_rays(true)
set_process(false)
iTime = 0.0
if sky_tex:
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/LIGHTING_STRENGTH",Vector3(0.0,0.0,0.0))
set_time()
func set_wind_strength(value: float):
wind_strength = value
if is_inside_tree():
call_deferred("set_call_deff_shader_params", clouds_tex.material, "shader_param/WIND",Vector3(wind_dir.x,0.0,wind_dir.y)*wind_strength);
func set_clouds_tint(value: Color):
clouds_tint = value;
if is_inside_tree():
call_deferred("set_call_deff_shader_params", sky_tex.material, "shader_param/clouds_tint",clouds_tint);
func thunder():
var thunder_sound:AudioStreamPlayer = $thunder;
if thunder_sound.is_playing():
#thunder_sound.stop()
return
thunder_sound.play()
await get_tree().create_timer(0.3).timeout;
set_lighting_strike(true)
await get_tree().create_timer(0.8).timeout;
set_lighting_strike(false)
func _set_exposure(value: float):
if god_rays:
god_rays.set_exposure(value)
func _set_attenuation(value: float):
if god_rays:
god_rays.set_attenuation(value)
func _set_light_size(value: float):
if god_rays:
god_rays.set_light_size(value)
func _set_god_rays(on: bool):
if not god_rays:
return
if on:
if !god_rays.is_inside_tree():
add_child(god_rays)
god_rays.light = sun
god_rays.set_clouds(clouds_view.get_texture())
else:
remove_child(god_rays)
# LERP COLOR
func hsv_lerp(cola, colb, t):
var h
var ha = cola.h
var hb = colb.h
var d = hb - ha;
if ha <= hb:
if d > 0.5:
h = fmod(lerp(ha + 1, hb, t), 1)
else:
h = lerp(ha, hb, t)
else:
d = -d;
if d > 0.5:
h = fmod(lerp(ha, hb + 1, t), 1)
else:
h = lerp(ha, hb, t)
#Setting the color
var newcol = Color()
newcol.v = lerp(cola.v, colb.v, t)
newcol.s = lerp(cola.s, colb.s, t)
newcol.h = h
return newcol
func set_call_deff_shader_params(node: Material, params: String, value):
node.set(params,value);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment