Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextureLayered subclasses don't serialize properly when created from a tool script #34312

Closed
Shfty opened this issue Dec 12, 2019 · 12 comments
Closed

Comments

@Shfty
Copy link

Shfty commented Dec 12, 2019

Godot version:
3.1.2 / 3.2 beta 3

OS/device including version:
Windows 10 Pro 10.0.18362 Build 18362

Issue description:
TextureLayered resources (as well as their Texture3D and TextureArray subclasses) can be created without issue via the import process by selecting the appropriate Import As option, but creating them from a tool script results in instances that can't be serialized.

I've been trying to use a TextureArray to implement a mipmap-friendly texture atlas for the Qodot project, which works well, but can't be saved into a scene due to this issue.

Steps to reproduce:

  • Open the project below
  • Open texture_array_test.tscn
  • Select the root scene node
  • Click the 'reload' checkbox in the inspector
  • A message detailing the contents of the created TextureArray will print to the log
  • Save the scene
  • The following error will appear in the log once per texture layer:
    • ERROR: Resource was not pre cached for the resource section, bug? At: scene/resources/resource_format_text.cpp:1372
  • Reload the scene
  • The following error will appear in the log, once per texture layer:
    -ERROR: _set_data: Condition ' !img.is_valid() ' is true. Continuing..: At: **scene/resources/texture.cpp:2093**
  • The TextureArray exported from the root node will now have empty layers

Minimal reproduction project:
TextureArrayBug.zip

@Shfty
Copy link
Author

Shfty commented Dec 12, 2019

I wrote a simple wrapper class to work around the problem for the use-case of TextureLayered-powered ShaderMaterials on MeshInstance nodes:
https://github.com/ShiftyAxel/TextureLayeredMesh

It's no fix, but it might help anyone having the same issue in the meantime.

arccoza added a commit to awkwardpolygons/cartographer that referenced this issue May 17, 2020
All TextureLayered classes fail to save properly with ResourceSaver,
so save_texarr was added as a temp workaround.
see: godotengine/godot#34312
@vwood
Copy link

vwood commented Oct 6, 2020

I couldn't get importing of TextureArrays to do anything useful at all in 3.2.2

@arccoza
Copy link

arccoza commented Oct 15, 2020

@vwood a bug was introduced in the LayeredTexture importer in 3.2.2, fixed in 3.2.3

@arccoza
Copy link

arccoza commented Oct 15, 2020

Working on Cartographer I ran into a lot of bugginess in TextureArray in Godot 3.2. You can't save a TextureArray in the scene, or in a .tres or .res file properly (it saves the image data, but the index array is filled with nulls), as well as a collection of other odd behaviour.

It looks like they're getting some attention in 4, but for now the importer is the only stable way to create TextureArrays natively, but its usefulness is limited.

So, long story short; I ended up creating a custom ResourceSaver for TextureArrays that saves them in the same format that the importer does, as a .texarr file. You don't need a custom ResourceLoader because the builtin loader understands .texarr files.

I also created a custom EditorImportPlugin for TextureArrays that builds them from simple JSON files. Just describe the TextureArray as a JSON structure of other images or textures, and the importer bungs them all in the TextureArray.

If they're useful to you, or others, I can extract them as a standalone plugin.

@Calinou
Copy link
Member

Calinou commented Oct 15, 2020

@arccoza Have you seen the TextureLayeredMesh add-on? If so, what did it miss?

@arccoza
Copy link

arccoza commented Dec 9, 2020

Hey @Calinou, sorry for the very slow response, I've had no time for Godot recently.
I've had a look at TextureLayeredMesh, and while it works at saving and loading, it's usecase specific, being bound to a custom node. Like my first attempts at solving this, it's a long workaround.

While fishing through Godots importer code for hints, I realized you only need a custom ResourceSaver that can save TextureArrays as the Godot .texarr file format. The builtin ResourceLoader will automatically load .texarr files with no problem.

Unfortunately the importer doesn't expose its save methods to GDScript, so I essentially re-implemented the importer save method in GDScript, as a ResourceSaver for TextureArrays. The benefits of this are you don't need any custom wrapper Nodes or Resources, and can save to .texarr from the editor save resource dropdown menu.

@woodbyte
Copy link

So, I've ran into this issue recently while trying to use precomputed/procedurally generated 3D textures to accelerate a raymarching shader which renders all sorts of nebulae in a space sim game.

I'd like to thank @Shfty for his workaround TextureLayeredMesh which seems to be a viable way forward for my project, and ask if anyone here knows if a fix is intended for some future 3.2.x release or if it will instead only be addressed in Godot 4 as hinted by @arccoza above.

Thank you.

@Calinou
Copy link
Member

Calinou commented Jan 30, 2021

I'd like to thank @Shfty for his workaround TextureLayeredMesh which seems to be a viable way forward for my project, and ask if anyone here knows if a fix is intended for some future 3.2.x release or if it will instead only be addressed in Godot 4 as hinted by @arccoza above.

As far as I know, nobody has looked at fixing this in the 3.2 branch yet. That said, since there are few knowledgeable contributors about texture arrays and importers, I doubt it will be fixed before 4.0 is released.

@arccoza
Copy link

arccoza commented Feb 14, 2021

I've extracted the tools and UI from Cartographer for working around this as a stand-alone plugin; BetterTextureArray, get it here: https://github.com/awkwardpolygons/better-texture-array
I hope you find it useful.

BetterTextureArray

@evanrinehart
Copy link

evanrinehart commented Jun 24, 2021

Godot 3.3.2.stable.official on windows 10

After struggling with creating a Texture3D from a tool script, which seems to work, and being unable to save and restore the resulting resource, I ran into a few interesting error messages.

  1. Make a scene which has a MeshInstance with an ArrayMesh with a surface with a ShaderMaterial with a shader with a param of type sampler3D. Clear this param in the editor and save the scene.
  2. Make a tool script which generates a Texture3D and sets it as the previously mentioned shader param. This much works for me.
  3. In the inspector try to save the Texture3D as .tres file. I get

Resource was not pre cached for the resource section, bug?

  1. In the inspector try to save the Texture3D as a .res file. I get

Resource was not pre cached for the resource section, most likely due to circular reference.

In either case the output file appears but with suspiciously low file size. As expected, these resources won't load and give

scene/resources/texture.cpp:2426 - Condition "!img.is_valid()" is true. Continuing. Once for each layer.

If you try to use ResourceSaver to save the Texture3D during runtime, not in a tool script, you get a similar message in the debugger (this one is for target file = .res)

write_variant: Resource was not pre cached for the resource section, most likely due to circular reference.

and the resulting file will similarly not load in the editor.

Epilogue: I installed arccoza's plugin mentioned above and now I can save my generated Texture3Ds as .tex3d files and it works very well! Cheers and I hope this is incorporated into Godot at some point!

@samuelbigos
Copy link

Apologies for bumping this thread without any significant new information. I wanted to drop in to say that I was also tearing my hair out at Godot's default behaviour when attempting to save a 3D texture from a tool script.

In my case I was generating a Texture3D with various noises in different channels, for some shader effects at runtime (to avoid a very expensive cost to generate the noise in the shader). I don't think this is a particularly rare or obscure use-case but I appreciate it might not be a high priority to resolve. But thank god I managed to find this conversation. @arccoza's addon works flawlessly to solve the import issue, while also adding some incredibly useful functionatlity to view the texture in editor (per channel even!).

It would be great if this was added to Godot at some point, at least a fix for the saving/importing issue.

@YuriSizov
Copy link
Contributor

Fixed by #71394.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants