反射探针

金属球在不使用屏幕空间反射的情况下映出一间彩色房间。三种粗糙度显示镜面变模糊的速度。

上方的编辑器正在运行这个项目。改一行代码,它就会重新加载。

用到的 Godot 类

ReflectionProbeStandardMaterial3DCamera3D

代码

scripts/main.gd
extends Node

const ROOM: float = 12.0
const WALL: float = 0.5
const HEIGHT: float = 9.0
const RING: float = 5.6

var camera: Camera3D
var angle: float = 0.0


func _ready() -> void:
	_add_environment()
	_add_room()
	_add_spheres()

	var lamp: OmniLight3D = OmniLight3D.new()
	lamp.position = Vector3(0, HEIGHT - 2.0, 1.5)
	lamp.light_energy = 3.4
	lamp.omni_range = 40.0
	add_child(lamp)

	# UPDATE_ALWAYS bakes a black cubemap in gl_compatibility, so the probe has to be added last
	var probe: ReflectionProbe = ReflectionProbe.new()
	probe.size = Vector3(ROOM * 2.0, HEIGHT, ROOM * 2.0)
	probe.position = Vector3(0, HEIGHT * 0.5, 0)
	probe.update_mode = ReflectionProbe.UPDATE_ONCE
	probe.box_projection = true
	probe.max_distance = 60.0
	add_child(probe)

	camera = Camera3D.new()
	add_child(camera)
	camera.current = true
	_place_camera()

	print('the camera circles the room and each sphere mirrors the four wall colors, without SSR')


func _process(delta: float) -> void:
	angle += delta * 0.08
	_place_camera()


func _place_camera() -> void:
	camera.position = Vector3(sin(angle), 0, cos(angle)) * 11.0 + Vector3(0, 4.5, 0)
	camera.look_at(Vector3(0, 1.9, 0), Vector3.UP)


func _add_spheres() -> void:
	var roughness: Array[float] = [0.02, 0.18, 0.4]

	for i in roughness.size():
		var turn: float = deg_to_rad(90.0 + i * 120.0)

		var mesh: SphereMesh = SphereMesh.new()
		mesh.radius = 1.3
		mesh.height = 2.6

		var material: StandardMaterial3D = StandardMaterial3D.new()
		material.albedo_color = Color('#c8ccd8')
		material.metallic = 1.0
		material.roughness = roughness[i]

		var sphere: MeshInstance3D = MeshInstance3D.new()
		sphere.mesh = mesh
		sphere.material_override = material
		sphere.position = Vector3(cos(turn), 0, sin(turn)) * RING + Vector3(0, 1.5, 0)
		add_child(sphere)


func _add_room() -> void:
	var span: float = ROOM * 2.0

	_add_slab(Vector3(span, WALL, span), Vector3(0, -WALL * 0.5, 0), '#2a2f3d')
	_add_slab(Vector3(span, WALL, span), Vector3(0, HEIGHT, 0), '#f3d48d')
	_add_slab(Vector3(span, HEIGHT, WALL), Vector3(0, HEIGHT * 0.5, -ROOM), '#8da5f3')
	_add_slab(Vector3(span, HEIGHT, WALL), Vector3(0, HEIGHT * 0.5, ROOM), '#f3d48d')
	_add_slab(Vector3(WALL, HEIGHT, span), Vector3(-ROOM, HEIGHT * 0.5, 0), '#fc7f7f')
	_add_slab(Vector3(WALL, HEIGHT, span), Vector3(ROOM, HEIGHT * 0.5, 0), '#8eef97')


func _add_slab(size: Vector3, at: Vector3, hex: String) -> void:
	var mesh: BoxMesh = BoxMesh.new()
	mesh.size = size

	var material: StandardMaterial3D = StandardMaterial3D.new()
	material.albedo_color = Color(hex)
	material.roughness = 0.85

	var slab: MeshInstance3D = MeshInstance3D.new()
	slab.mesh = mesh
	slab.material_override = material
	slab.position = at
	add_child(slab)


func _add_environment() -> void:
	var sky_material: ProceduralSkyMaterial = ProceduralSkyMaterial.new()
	sky_material.sky_top_color = Color(0.05, 0.06, 0.12)
	sky_material.sky_horizon_color = Color(0.12, 0.14, 0.22)
	sky_material.ground_bottom_color = Color(0.02, 0.02, 0.04)
	sky_material.ground_horizon_color = Color(0.09, 0.1, 0.15)

	var sky: Sky = Sky.new()
	sky.sky_material = sky_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 = 0.4

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

更多3D 场景示例