This simple addon draws a reflective sphere for the selected reflection probe:
Been missing it a lot in godot because it can be hard to understand what’s going on with reflections in the scene when you don’t have clean reflective assets around. It allows to quickly see how different settings such as probe render distance and culling masks affect the final rendered reflection.
It also makes it easier to spot engine bugs, like this or this.
Addon
Here’s the full code:
@tool
extends EditorPlugin
var _instance: RID
var _mesh: Mesh
var _probe: ReflectionProbe
func _enter_tree() -> void:
EditorInterface.get_selection().selection_changed.connect(_update_preview)
_create_instance()
func _exit_tree() -> void:
EditorInterface.get_selection().selection_changed.disconnect(_update_preview)
_clear_instance()
func _create_instance() -> void:
_instance = RenderingServer.instance_create()
_mesh = SphereMesh.new()
_mesh.radius = 0.5
_mesh.height = _mesh.radius * 2.0
var material = StandardMaterial3D.new()
material.roughness = 0
material.metallic = 1
_mesh.surface_set_material(0, material)
RenderingServer.instance_geometry_set_cast_shadows_setting(_instance, RenderingServer.SHADOW_CASTING_SETTING_OFF)
RenderingServer.instance_set_base(_instance, _mesh)
func _clear_instance() -> void:
if _instance:
RenderingServer.free_rid(_instance)
if _mesh:
RenderingServer.free_rid(_mesh)
func _update_preview() -> void:
var selection = EditorInterface.get_selection().get_selected_nodes()
if selection.size() == 1 and selection[0] is ReflectionProbe:
_probe = selection[0]
var scenario: RID = EditorInterface.get_edited_scene_root().get_world_3d().scenario
RenderingServer.instance_set_scenario(_instance, scenario)
RenderingServer.instance_set_visible(_instance, true)
return
RenderingServer.instance_set_visible(_instance, false)
_probe = null
func _process(_delta: float) -> void:
if not _instance.is_valid() or not _probe:
return
var probe_transform = _probe.global_transform
var origin_offset = _probe.origin_offset
var instance_transform = probe_transform * Transform3D(Basis(), origin_offset)
RenderingServer.instance_set_transform(_instance, instance_transform)
And zip:
It’s currently drawing a 0.5m sphere. I thought about making it fixed-size so that it stays the same in the viewport when you zoom, but realized that it’s a downgrade because it can be useful to be able to zoom into the probe to look at the details.
It also takes probe’s origin offset into the account because that’s where it’s rendered from.
In this addon we’re only drawing the preview for one selected probe. We could instantiate them dynamically for multiple probes, but tbh so far I haven’t felt the need to look at more than one at a time.
RenderingServer
As you can see we’re creating the sphere instance directly via the RenderingServer
instead of making a node for it because we don’t want previews to be saved as part of the scene.
You can use this for all kinds of editor tools to draw gizmos of any complexity.
Since RenderingServer
doesn’t use nodes, it relies on special pointers of RID
class to indirectly reference objects. RenderingServer
is a low-level rendering API and it’s implemented in opaque fashion to allow godot to easily support different rendering APIs and platforms. You can read more about godot servers here.