godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Create Texture2DArray resource in editor with separate images #10601

Open copygirl opened 2 weeks ago

copygirl commented 2 weeks ago

Describe the project you are working on

A 3D game with custom terrain rendered using a Texture2DArray.

Describe the problem or limitation you are having in your project

Texture2DArray resource can only be created in the editor by importing a single image as a texture atlas. In code, one can use the create_from_images to use multiple separate images, but if the resulting resource is saved, it ends up embedding the images into the .tres or .tscn file as packed byte arrays.

Strangely enough, Texture2DArray does actually save the separate layers as an image array in its _images property, and setting it to use a bunch of ExtResource by manually editing the file, instead of the embedded SubResources, appears to work fine. Though it looks like the editor will at some point convert them to SubResource anyway?

Describe the feature / enhancement and how it helps to overcome the problem or limitation

When creating a new Texture2DArray in the inspector, expose the _images array as an editable property, allowing you to add separate images as layers. (Texture2DArray might not be the only type of resource that could benefit from this.)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

image

If this enhancement will not be used often, can it be worked around with a few lines of script?

From what I can tell, the two workarounds are flawed:

Is there a reason why this should be core and not an add-on in the asset library?

Unsure if this would be possible as an add-on at all.

KoBeWi commented 2 weeks ago

In code, one can use the create_from_images to use multiple separate images, but if the resulting resource is saved, it ends up embedding the images into the .tres or .tscn file as packed byte arrays.

What images are you using for the texture array? If they are linked to a file (i.e. loaded via load()), they shouldn't get embedded.

copygirl commented 2 weeks ago

@KoBeWi I used an exported image array property whose setter would pass its value to the create_from_images function, and then to set_shader_parameter of a ShaderMaterial. I dragged the images (imported as Image) into this property from the FileSystem dock.

KoBeWi commented 2 weeks ago

Looks like a bug to me tbh. You can work it around by creating the texture from Array of images at runtime, unless you need it in the editor.

copygirl commented 2 weeks ago

Yeah I thought about that too, but I do need it in the editor.

copygirl commented 2 weeks ago

For the record, here is my terrain_material.tres file that I have manually edited to use ExtResource:

[gd_resource type="ShaderMaterial" load_steps=7 format=4 uid="uid://doe8owgx4jeu1"]

[ext_resource type="Shader" path="res://terrain/terrain_shader.gdshader" id="1_mf55c"]
[ext_resource type="Image" uid="uid://b0jp1dyxugbr7" path="res://assets/textures/terrain/grass.png" id="5_mau31"]
[ext_resource type="Image" uid="uid://bpo7mkr6sctqr" path="res://assets/textures/terrain/dirt.png" id="6_xc3ue"]
[ext_resource type="Image" uid="uid://dqyqg6yt7yk3k" path="res://assets/textures/terrain/rock.png" id="7_84wdo"]
[ext_resource type="Image" uid="uid://bkwjxg6g2itag" path="res://assets/textures/terrain/sand.png" id="8_3fpcn"]

[sub_resource type="Texture2DArray" id="Texture2DArray_3nq13"]
_images = Array[Image]([ExtResource("5_mau31"), ExtResource("6_xc3ue"), ExtResource("7_84wdo"), ExtResource("8_3fpcn")])

[resource]
render_priority = 0
shader = ExtResource("1_mf55c")
shader_parameter/textures = SubResource("Texture2DArray_3nq13")

This loads fine when I restart the editor.

However, when I save the scene this material is used in, the changes I made manually revert. In addition, I noticed that this message box appears when I save without any scene open, after:

The current scene has no root node, but 1 modified external resource(s) and/or plugin data were saved anyway.

Here is what the file looks like zoomed out without my changes:

image

I obviously don't want to commit this to git. Imagine this with more than 4 images, and ones larger than 64x64.

copygirl commented 2 weeks ago

For now, my workaround looks like this:

Of course this is far from ideal. If I do make any changes to the material, I need to forcefully add the file to git (git add -f) to commit those changes. If I want to add any more images to the Texture2DArray I need to go through the annoying process of manually modifying the file.


edit: Correction, the correct command is git update-index --assume-unchanged <file>, because adding the file to .gitignore does nothing when the file is already tracked. Doing so comes with a lot of downsides though, such as every developer having to run the command on their side, and issues arising when you do want to make changes and someone else tries to pull the changes.