Tour des lumières

La même géométrie et le même matériau blanc trois fois. Un cull mask donne à chaque lumière son tiers de la scène.

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

Classes Godot utilisées

OmniLight3DSpotLight3DDirectionalLight3D

Le code

scripts/main.gd
extends Node

const STATIONS: Array[Dictionary] = [
	{at = -8.0, title = 'OmniLight3D', color = '#8da5f3'},
	{at = 0.0, title = 'SpotLight3D', color = '#8eef97'},
	{at = 8.0, title = 'DirectionalLight3D', color = '#f3d48d'},
]


func _ready() -> void:
	_add_environment()

	for i in STATIONS.size():
		var station: Dictionary = STATIONS[i]
		var mask: int = 1 << i

		_add_station(station.at, station.title, mask)
		_add_light(i, station, mask)

	var camera: Camera3D = Camera3D.new()
	camera.fov = 56.0
	camera.position = Vector3(0, 6.0, 13.5)
	add_child(camera)
	camera.look_at(Vector3(0, 1.6, 0), Vector3.UP)
	camera.current = true

	print('same geometry and same white material three times, only the light node changes')


func _add_light(index: int, station: Dictionary, mask: int) -> void:
	var light: Light3D

	if index == 0:
		var omni: OmniLight3D = OmniLight3D.new()
		omni.position = Vector3(station.at, 3.4, 1.2)
		omni.omni_range = 11.0
		omni.light_energy = 5.0
		light = omni
	elif index == 1:
		var spot: SpotLight3D = SpotLight3D.new()
		spot.position = Vector3(station.at, 6.4, 0.6)
		spot.rotation_degrees = Vector3(-90, 0, 0)
		spot.spot_range = 16.0
		spot.spot_angle = 26.0
		spot.spot_angle_attenuation = 0.6
		spot.light_energy = 9.0
		light = spot
	else:
		var sun: DirectionalLight3D = DirectionalLight3D.new()
		sun.rotation_degrees = Vector3(-48, -32, 0)
		sun.light_energy = 1.5
		light = sun

	# without a cull mask the directional light would wash out the other two stations
	light.light_cull_mask = mask
	light.light_color = Color(station.color)
	add_child(light)


func _add_station(at: float, title: String, mask: int) -> void:
	_add_mesh(_slab(), Vector3(at, -0.2, 0), mask)
	_add_mesh(_ball(), Vector3(at - 1.7, 0.9, 0.7), mask)
	_add_mesh(_block(), Vector3(at + 1.6, 0.7, -0.6), mask)
	_add_mesh(_post(), Vector3(at + 0.1, 1.1, 1.7), mask)

	var label: Label3D = Label3D.new()
	label.text = title
	label.font_size = 60
	label.pixel_size = 0.007
	label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
	label.alpha_cut = Label3D.ALPHA_CUT_DISCARD
	label.modulate = Color('#c8ccd8')
	label.outline_size = 14
	label.outline_modulate = Color(0, 0, 0, 0.9)
	label.position = Vector3(at, 4.2, 0)
	add_child(label)


func _add_mesh(mesh: Mesh, at: Vector3, mask: int) -> void:
	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color('#d6dae4')
	material.roughness = 0.55

	var instance: MeshInstance3D = MeshInstance3D.new()
	instance.mesh = mesh
	instance.material_override = material
	instance.position = at
	instance.layers = mask
	add_child(instance)


func _slab() -> BoxMesh:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = Vector3(6.4, 0.4, 6.4)

	return mesh


func _ball() -> SphereMesh:
	var mesh: SphereMesh = SphereMesh.new()
	mesh.radius = 0.9
	mesh.height = 1.8

	return mesh


func _block() -> BoxMesh:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = Vector3(1.4, 1.4, 1.4)

	return mesh


func _post() -> CylinderMesh:
	var mesh: CylinderMesh = CylinderMesh.new()
	mesh.top_radius = 0.5
	mesh.bottom_radius = 0.5
	mesh.height = 2.2

	return mesh


func _add_environment() -> void:
	var env: Environment = Environment.new()
	env.background_mode = Environment.BG_COLOR
	env.background_color = Color(0.03, 0.035, 0.06)
	env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
	env.ambient_light_color = Color(0.4, 0.45, 0.62)
	env.ambient_light_energy = 0.18

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

Plus d'exemples de Scène 3D