How can I create a visible light beam for the Spotlight?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Gamemap

I want to create a stage scene with fog and spotlights, but I can’t make the beam visible.
I would like to color the parts of the fog (Godot 4.0) that the beam goes through in the color of the spotlights (currently I only see the option to color the entire fog node).
If this is not possible, I would like to create a beam without the fog node.

I want to create something like this:

:bust_in_silhouette: Reply From: cm

I haven’t had much success with visible light in volumetric fog, but I recently wrote a quick script to fake it with a transparent cylinder. This is pretty crude, and may or may not work for you, but here’s my script which can be dropped directly onto a spotlight:

extends SpotLight3D

@export var length: float = 6.0
@export_range(0.0, 1.0, 0.01) var falloff: float = 1.0
@export_range(0.0, 1.0, 0.01) var opacity: float = 0.2


var _cone_mesh: MeshInstance3D = null


func _ready() -> void:
	_cone_mesh = MeshInstance3D.new()
	var cylinder = CylinderMesh.new()
	cylinder.material = build_material()

	_cone_mesh.mesh = cylinder
	_cone_mesh.cast_shadow = false

	add_child(_cone_mesh)
	update_position()
	update_cone()


func build_material() -> StandardMaterial3D:
	var mat = StandardMaterial3D.new()
	mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
	mat.blend_mode = BaseMaterial3D.BLEND_MODE_ADD
	mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
	var grad = Gradient.new()
	grad.set_color(0, Color(light_color, opacity))
	grad.set_color(1, Color(light_color, 0.0))
	var grad_tex = GradientTexture2D.new()
	grad_tex.gradient = grad
	grad_tex.fill_from = Vector2(0.0, 0.0)
	grad_tex.fill_to = Vector2(0.0, 0.5 * falloff)
	mat.albedo_texture = grad_tex
	return mat


func update_position() -> void:
	_cone_mesh.rotation.x = PI * 0.5
	_cone_mesh.position.z = length * -0.5


func update_cone() -> void:
	var a = deg2rad(spot_angle)
	var b = PI * 0.5
	var c = PI - (a + b)
	_cone_mesh.mesh.top_radius = 0.0
	_cone_mesh.mesh.bottom_radius = length * sin(a) / sin(c)
	_cone_mesh.mesh.height = length

Thank you!
I will try your code this weekend.

Gamemap | 2022-05-12 16:02

In Godot 4.0 you can use now the FogVolume Node. (GH-Discussion-4557)

Gamemap | 2022-05-18 20:49