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

Allow to extend existing texture importers #1943

Open
Zylann opened this issue Dec 5, 2020 · 0 comments
Open

Allow to extend existing texture importers #1943

Zylann opened this issue Dec 5, 2020 · 0 comments

Comments

@Zylann
Copy link

Zylann commented Dec 5, 2020

Describe the project you are working on

A terrain plugin

Describe the problem or limitation you are having in your project

Texturing the ground of a terrain is challenging. To be efficient, it requires packing a bunch of images together (albedo, normals, bump, roughness etc.) into either textures, or texture arrays, in order to need as few texture fetches as possible in the shader.

It is tedious for users to do this, so I needed to make a tool pipeline for them to import images into this kind of textures.

This is what my custom importers do:

image

As you can see, I defined a new file type holding special information just so I could hook in a different importer. It allows to directly import from source images to the expected texture resources. But because the imported outputs are standard StreamTexture and TextureArray, this would need to piggyback on features that already exist within ResourceImporterTexture and ResourceImporterLayeredTexture.

In the case of StreamTexture, it's mostly a matter or replacing the source of the image, but for TextureLayered the whole part where it takes an atlas is also unnecessary.

From the outside it's really clean to use without intermediary steps, but it's incredibly tedious to implement, and not robust for several reasons:

  • There is no API at all to access or customize those functionalities, so I ended up re-implementing those two importers from scratch in GDScript, just so I could tweak the parts I was interested in: https://github.com/Zylann/godot_heightmap_plugin/tree/master/addons/zylann.hterrain/tools/packed_textures
  • These importers use magic numbers sometimes, made it hard to reverse-engineer
  • The same options don't always have the same IDs between texture resources and importers
  • Lossless compression is abstracted in Godot but in GDScript I had to explicitely write it as PNG
  • WebM compression is not available to the script API so I could not implement Lossy compression
  • Some Image detection functions are not exposed so I could not implement some optimizations (fortunately, I did not need them)
  • Some stuff I even failed to understand and had to ignore.
  • Because none of this has an API, a new version of Godot could likely break it.

Finally, this is not the only use case I had. In the past I also wanted it to customize mipmaps, and other people also want to do that: godotengine/godot#24381, godotengine/godot#28802

I can see other use cases as well such as indexed colors, a topic that comes up often with palette swap and could be used by a plugin: paint with conventional colors, import by recognizing colors and replacing them with an index to obtain a greyscale texture, then use the indexes with a palette in shader.

I also wasn't the only one to need re-implementating an importer, as you can see in this plugin: https://github.com/awkwardpolygons/cartographer/blob/master/addons/cartographer/texture_array_builder.gd (claims TextureLayered importer is buggy as well)

But even for simpler cases, I found a lot of plugins out there that add support for other formats by making an import plugin, and they have to re-implement the thing too.
Here the author apparently skipped implementing all features and hardcodes it as PNG without VRAM compression:
https://github.com/Technohacker/godot_pixelorama_importer/blob/master/addons/godot_pixelorama_importer/pixelorama_importer.gd

And here, missing all features as well and hardcoding everything:
https://github.com/lifelike/godot-animator-import/blob/master/addons/aaimport/aa_import_plugin.gd

Aaand another here, again hardcoded to oblivion:
https://github.com/Technohacker/godot_piskel_importer/blob/master/addons/godot_piskel_importer/piskel_importer.gd#L96

And another copied from Cartographer:
https://github.com/awkwardpolygons/better-texture-array

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

It could be a simple as extending from a base importer class to customize the steps. Implementing a virtual function and using helper methods to run built-in steos, or having multiple virtual functions to customize specific steps.

To do things such as:

  • Reading the source file into an image (to add new formats)
  • Processing the image (like shown above with channel packing)
  • Generating custom mipmaps
  • Feeding data in a specific way to create the Texture2D/Texture3D (notably if the "atlas" approach doesnt suits you)
  • ...

This way, all the rewriting part would no longer be required.
There might also be a way to implement part of this proposal with solely a custom image format loader (which the builtin texture importer would have to use).

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

It can mostly be worked around, but as you saw, it's really not a few lines of code. Otherwise people keep hardcoding one path and don't even implement (or know about?) the other features Godot is supposed to support.

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

Because the import logic of textures is in core, and having to re-implement and maintain a 90%-working copy is not robust.

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

2 participants