Created
August 11, 2022 11:11
-
-
Save RemyCampanals/044fe42ed5c336780d21bc77ca67c0ac to your computer and use it in GitHub Desktop.
Sky.gd for Godot 4.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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