Shader de ciel

Un coucher de soleil procédural avec des étoiles, écrit en shader_type sky. Le disque solaire suit le nœud de lumière.

L'éditeur ci-dessus fait tourner ce projet. Changez une ligne et il se recharge.

Classes Godot utilisées

SkyShaderMaterialDirectionalLight3D

Le code

scripts/main.gd
extends Node

var sun: DirectionalLight3D
var elapsed: float = 0.0


func _ready() -> void:
	var material: ShaderMaterial = ShaderMaterial.new()
	material.shader = Get.shader('sky')

	var sky: Sky = Sky.new()
	sky.sky_material = material

	var env: Environment = Environment.new()
	env.background_mode = Environment.BG_SKY
	env.sky = sky
	env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
	env.ambient_light_energy = 1.0

	var world: WorldEnvironment = WorldEnvironment.new()
	world.environment = env
	add_child(world)

	sun = DirectionalLight3D.new()
	sun.light_energy = 1.2
	add_child(sun)

	_add_ground()

	for i in 5:
		_add_rock(Vector3(cos(i * 1.3) * (3.0 + i), 0.4, sin(i * 1.3) * (3.0 + i)))

	var camera: Camera3D = Camera3D.new()
	camera.position = Vector3(0, 1.6, 9)
	add_child(camera)
	camera.look_at(Vector3(0, 2.4, 0), Vector3.UP)
	camera.current = true

	print('the sky is a shader, and the sun disc follows the DirectionalLight3D')


func _process(delta: float) -> void:
	elapsed += delta
	sun.rotation_degrees = Vector3(-8.0 - 22.0 * sin(elapsed * 0.25), -40.0 + elapsed * 6.0, 0)


func _add_ground() -> void:
	var mesh: PlaneMesh = PlaneMesh.new()
	mesh.size = Vector2(60, 60)

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#1b2030')
	material.roughness = 0.9

	var ground: MeshInstance3D = MeshInstance3D.new()
	ground.mesh = mesh
	ground.material_override = material
	add_child(ground)


func _add_rock(at: Vector3) -> void:
	var mesh: PrismMesh = PrismMesh.new()
	mesh.size = Vector3(1.6, 2.2, 1.6)

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#232a3d')
	material.roughness = 0.8

	var rock: MeshInstance3D = MeshInstance3D.new()
	rock.mesh = mesh
	rock.material_override = material
	rock.position = at + Vector3(0, 1.1, 0)
	add_child(rock)
shaders/sky.gdshader
shader_type sky;

uniform vec3 zenith_color: source_color = vec3(0.05, 0.12, 0.35);
uniform vec3 horizon_color: source_color = vec3(0.85, 0.45, 0.3);
uniform vec3 ground_color: source_color = vec3(0.03, 0.03, 0.05);
uniform vec3 sun_color: source_color = vec3(1.0, 0.85, 0.6);
uniform float sun_size = 400.0;
uniform float star_amount = 0.6;

float hash(vec2 p) {
	return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}

void sky() {
	float height = EYEDIR.y;
	vec3 color = mix(horizon_color, zenith_color, pow(clamp(height, 0.0, 1.0), 0.45));

	if (height < 0.0) {
		color = mix(horizon_color, ground_color, clamp(-height * 3.0, 0.0, 1.0));
	}

	vec2 star_uv = floor(EYEDIR.xz / max(abs(EYEDIR.y), 0.05) * 90.0);
	float star = step(1.0 - star_amount * 0.02, hash(star_uv));
	color += vec3(star) * clamp(height, 0.0, 1.0);

	if (LIGHT0_ENABLED) {
		float sun = pow(max(dot(EYEDIR, LIGHT0_DIRECTION), 0.0), sun_size);
		color += sun_color * sun * LIGHT0_ENERGY;
	}

	COLOR = color;
}

Plus d'exemples de Shaders