Last active
December 20, 2024 22:27
-
-
Save partybusiness/8b22700435d1d5943285618c75971e45 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @tool | |
| extends EditorScript | |
| class_name GenerateCubemapEditorScript | |
| # collection of helper scripts for generating cubemaps | |
| # file you wish to output the generated cubemap to | |
| var cubemap_filename:String = "color_test_cubemap.tres" | |
| # file you wish to output the generated cubemap to | |
| var cubemap_image_filename:String = "color_test_cubemap.png" | |
| # name of a Node3D in the currently open scene used as a camera position | |
| # if you aren't using one, you can leave it blank | |
| var camera_position_node3D:String = "" | |
| # size of image generated per side from camera | |
| var image_size:int = 2048 | |
| # single = apply same image to each side of the cubemap | |
| # six = provide six image textures for each side of the cubemap | |
| # camera = renders six images from the currently open scene | |
| enum GenModes {single, six, camera} | |
| # call by using File -> Run in Script Editor | |
| # set value of mode below for which method you want to use | |
| # then go to the corresponding function and set any variables followed with # SET VALUE | |
| func _run() -> void: | |
| var mode:GenModes = GenModes.camera # change this for other modes | |
| match mode: | |
| GenModes.single: | |
| gen_single() | |
| GenModes.six: | |
| gen_six() | |
| GenModes.camera: | |
| gen_camera() | |
| func gen_single() -> void: | |
| var default_image:Image = flip_image(Image.load_from_file("res://icon.svg")) # SET VALUE | |
| var new_cubemap:Cubemap = Cubemap.new() | |
| # Front (+X), Back (-X), Top (+Y), Bottom (-Y), Left (+Z), Right (-Z) | |
| var all_images:Array[Image] = [default_image, default_image, default_image, default_image, default_image, default_image] | |
| new_cubemap.create_from_images(all_images) | |
| ResourceSaver.save(new_cubemap, "res://" + cubemap_filename) | |
| func gen_six() -> void: | |
| # NOTE: images are flipped to match the results when using EYEDIR on a samplerCube in a shader | |
| var new_cubemap:Cubemap = Cubemap.new() | |
| var right_image:Image = flip_image(Image.load_from_file("res://dice/five.png")) # SET VALUE | |
| var left_image:Image = flip_image(Image.load_from_file("res://dice/two.png")) # SET VALUE | |
| var top_image:Image = flip_image(Image.load_from_file("res://dice/four.png")) # SET VALUE | |
| var bottom_image:Image = flip_image(Image.load_from_file("res://dice/three.png")) # SET VALUE | |
| var back_image:Image = flip_image(Image.load_from_file("res://dice/six.png")) # SET VALUE | |
| var front_image:Image = flip_image(Image.load_from_file("res://dice/one.png")) # SET VALUE | |
| # NOTE: I encountered one claim that the order is Front, Back, Top, Bottom, Left, Right | |
| # but if I interpret a zero-rotation camera as facing forward, the following is more correct: | |
| var all_images:Array[Image] = [right_image, left_image, top_image, bottom_image, back_image, front_image] | |
| new_cubemap.create_from_images(all_images) | |
| ResourceSaver.save(new_cubemap, "res://" + cubemap_filename) | |
| static func flip_image(source:Image, down_scale:int = 1) -> Image: | |
| var new_image:Image = source.duplicate(true) | |
| for x in range(0, source.get_width()): | |
| for y in range(0, source.get_height()): | |
| new_image.set_pixel(x, y, source.get_pixel(source.get_width() - x - 1, y)) | |
| if down_scale > 1: | |
| new_image.resize(source.get_width() / down_scale, source.get_height() / down_scale, Image.INTERPOLATE_LANCZOS) | |
| return new_image | |
| func gen_camera() -> void: | |
| print(get_scene().name) | |
| # I couldn't find a good way to render from a camera in an EditorScript so I'm forced | |
| #to add an @tool Node to the scene and let that handle the actual rendering. | |
| # But I couldn't get EditorInterface.edit_node() to work on the @tool Node so I still | |
| #need this EditorScript | |
| var get_position:Vector3 = Vector3.ZERO | |
| # check if the scene contains a position node to override get_position | |
| if camera_position_node3D.length()>0: | |
| var position_source:Node3D = get_scene().find_child(camera_position_node3D) | |
| if position_source != null: | |
| get_position = position_source.global_position | |
| var new_gen = GenerateCubemapFromCamera.new() | |
| new_gen.name = "GenerateCubemapFromCamera" | |
| get_scene().add_child(new_gen) | |
| new_gen.owner = get_scene() | |
| new_gen.vrs_update_mode = Viewport.VRS_UPDATE_ALWAYS | |
| new_gen.size = Vector2i(image_size, image_size) | |
| new_gen.world_3d = new_gen.get_world_3d() | |
| #instantiate camera | |
| var camera = Camera3D.new() | |
| new_gen.add_child(camera) | |
| camera.fov = 90.0 | |
| camera.name = "camera_name" | |
| camera.global_position = get_position | |
| camera.owner = get_scene() | |
| new_gen.camera = camera | |
| new_gen.image_size = image_size | |
| new_gen.cubemap_filename = cubemap_image_filename | |
| EditorInterface.edit_node(new_gen) #need viewport selected or it won't render | |
| new_gen.run_now = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @tool | |
| extends SubViewport | |
| class_name GenerateCubemapFromCamera | |
| @export var run_now:bool = false | |
| @export var image_size:int = 4096 | |
| @export var down_scale:int = 4 | |
| @export var cubemap_filename:String = "camera_cubemap.png" | |
| @export var camera:Camera3D | |
| func _process(_delta: float) -> void: | |
| if run_now: | |
| run_now = false | |
| size = Vector2i.ONE * image_size * down_scale | |
| # NOTE: images are flipped to match the results when using EYEDIR on a samplerCube in a shader | |
| await get_tree().process_frame # bonus frame wait | |
| camera.rotation_degrees = Vector3(0.0, 0.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var front_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| camera.rotation_degrees = Vector3(0.0, 180.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var back_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| camera.rotation_degrees = Vector3(90.0, 180.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var top_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| camera.rotation_degrees = Vector3(-90.0, 180.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var bottom_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| camera.rotation_degrees = Vector3(0.0, 90.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var left_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| camera.rotation_degrees = Vector3(0.0, -90.0, 0.0) | |
| await get_tree().process_frame # wait for camera to render | |
| var right_image:Image = GenerateCubemapEditorScript.flip_image(get_texture().get_image(), down_scale) | |
| await get_tree().process_frame # bonus frame wait | |
| var all_images:Array[Image] = [right_image, left_image, top_image, bottom_image, back_image, front_image] | |
| save_cubemap_png(all_images, "res://" + cubemap_filename) | |
| print("complete") | |
| #self.queue_free() # removes itself after finishing | |
| func save_cubemap_png(all_images:Array[Image], path_name:String) -> void: | |
| # assumes images are in order: [right_image, left_image, top_image, bottom_image, back_image, front_image] | |
| var image_size:Vector2i = Vector2i(all_images[0].get_width(), all_images[0].get_height()) | |
| var new_image:Image = Image.create(image_size.x * 3, image_size.y * 2, false, all_images[0].get_format()) | |
| var index:int = 0 | |
| var source_rect:Rect2i = Rect2i(0, 0, image_size.x, image_size.y) | |
| new_image.blit_rect(all_images[0], source_rect, Vector2i(0, 0)) # right | |
| new_image.blit_rect(all_images[1], source_rect, Vector2i(image_size.x, 0)) # left | |
| new_image.blit_rect(all_images[2], source_rect, Vector2i(image_size.x * 2, 0)) # top | |
| new_image.blit_rect(all_images[3], source_rect, Vector2i(0, image_size.y)) # bottom | |
| new_image.blit_rect(all_images[4], source_rect, Vector2i(image_size.x, image_size.y)) # back | |
| new_image.blit_rect(all_images[5], source_rect, Vector2i(image_size.x * 2.0, image_size.y)) # front | |
| new_image.save_png(path_name) | |
| # set up import settings on the image | |
| await get_tree().process_frame | |
| EditorInterface.get_resource_filesystem().scan() # | |
| await get_tree().process_frame | |
| var import_settings:ConfigFile = ConfigFile.new() | |
| import_settings.load(path_name + ".import") | |
| print(import_settings) | |
| import_settings.set_value("remap", "importer", "cubemap_texture") | |
| import_settings.set_value("remap", "type", "CompressedCubemap") | |
| import_settings.set_value("params", "slices/arrangement", 2) | |
| import_settings.set_value("params", "mipmaps/generate", false) | |
| import_settings.save(path_name + ".import") | |
| EditorInterface.get_resource_filesystem().scan() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| shader_type sky; | |
| uniform samplerCube sky_cube:source_color; | |
| void sky() { | |
| COLOR = texture(sky_cube, EYEDIR).rgb; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| shader_type spatial; | |
| render_mode unshaded; | |
| uniform samplerCube sky_cube:source_color; | |
| varying vec3 world_position; | |
| void vertex() | |
| { | |
| world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; | |
| } | |
| void fragment() { | |
| vec3 view_dir = world_position - CAMERA_POSITION_WORLD; | |
| ALBEDO = texture(sky_cube, view_dir).rgb; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment