@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