MagicNStuff/source/tools/cubemap_generator.gd
SchimmelSpreu83 9dc31a11f6 Refactored Interaction and Save System
- Added a save override confirmation in main menu.
- Added Interaction types.
- Added some test interactions.
- Also added a ViewRollEffect for the player camera.
- Also also added a cubemap generator (CubeMapGeneratorCamera).
2026-01-03 12:45:39 +01:00

109 lines
2.8 KiB
GDScript

@tool
class_name CubeMapGeneratorCamera
extends Camera3D
## https://danilw.github.io/GLSL-howto/cubemap_to_panorama_js/cubemap_to_panorama.html
const RESOLUTIONS: PackedInt32Array = [
2,
4,
8,
16,
32,
64,
128,
256,
512,
1024,
2048,
4096,
8192,
]
const AXIS_NAMES: Dictionary[int, String] = {
0: "Front", 1: "Left", 2: "Back", 3: "Right", 4: "Up", 5: "Down"
}
const CAMERA_ALIGNMENTS: Dictionary[int, Vector3] = {
0: Vector3.ZERO, # Forward
1: Vector3(0.0, -90.0, 0.0), # Left
2: Vector3(0.0, 180.0, 0.0), # Back
3: Vector3(0.0, 90.0, 0.0), # Right
4: Vector3(90.0, 90.0, 0.0), # Up
5: Vector3(-90.0, 90.0, 0.0),# Down
}
@warning_ignore("unused_private_class_variable")
@export_tool_button("Generate Cubemaps", "Cubemap") var _gen: Callable = generate_cubemaps
@export var resolution: int = 8
@export var msaa := SubViewport.MSAA.MSAA_8X
@export var ssaa := SubViewport.ScreenSpaceAA.SCREEN_SPACE_AA_SMAA
@export_global_dir var output_directory: String = "user://cubemaps/"
func _validate_property(property: Dictionary) -> void:
if property.name == "resolution":
var enums: String = str(RESOLUTIONS).replace("[", "").replace("]", "").replace(" ", "")
property.type = TYPE_INT
property.hint = PROPERTY_HINT_ENUM
property.hint_string = enums
func generate_cubemaps() -> void:
if not DirAccess.dir_exists_absolute(output_directory):
push_error("Directory '%s' does not exist. Please create it." % output_directory)
return
var camera: Camera3D = duplicate()
camera.fov = 90.0
for child: Node in camera.get_children():
child.queue_free()
var viewport := SubViewport.new()
viewport.msaa_3d = msaa
viewport.screen_space_aa = ssaa
viewport.size = get_resolution()
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
add_child(viewport)
viewport.owner = get_owner()
viewport.add_child(camera)
camera.owner = get_owner()
camera.global_position = global_position
camera.make_current()
for axis: int in range(6):
camera.rotation_degrees = CAMERA_ALIGNMENTS[axis]
await take_screenshot(viewport, axis)
#await get_tree().create_timer(3.0).timeout
#await get_tree().create_timer(15.0).timeout
viewport.queue_free()
func take_screenshot(viewport: SubViewport, axis_index: int) -> void:
await RenderingServer.frame_post_draw
var image: Image = viewport.get_texture().get_image()
var file: String = str(_get_scene_name(), "_", AXIS_NAMES[axis_index], ".png")
var filepath: String = output_directory.path_join(file)
image.save_png(filepath)
func get_resolution() -> Vector2i:
@warning_ignore("narrowing_conversion")
var _resolution: int = pow(2.0, 1 + resolution)
return Vector2i.ONE * _resolution
func _get_scene_name() -> String:
if Engine.is_editor_hint():
return Engine.get_singleton(&"EditorInterface").get_edited_scene_root().name
return owner.name