Open Zylann opened 3 years ago
Seems to be a nice workflow improvement. What are the drawbacks?
@RonanZe if you only want to use albedo textures without normals, without fancy blending, and only 4 textures, then you might find the process a bit redundant compared to assigning textures directly without import step (although Godot still imports from PNGs to STEXs in any case).
I was in the testing phase when I found the following blockers.
I was hoping that I would be able to generate StreamTextures
or TextureArray
from code, save them, assign them to the TextureSet
resource, and finally save it. Simple? NOPE:
1: generating native Godot formats (.texarr, .stex) really sucks. ResourceSaver
does not allow to save TextureArray
resources, and StreamTexture
can't even be made from scripts.
So I ended up re-implementing the entire logic of texture importers in GDScript... sadly there is a bunch of things GDScript can't do because they are not exposed, in particular when dealing with image compression.
2: it appears some VRAM compression formats may depend on feature tags sent to EditorImportPlugin
, depending on your project settings and the platforms you export for... which means to produce these imported formats, I would HAVE to write one. But the problem is, the import dock won't let me do anything close to the nice free UI I posted earlier.
3: if I have to make an EditorImportPlugin
, it means TextureSet
can't be the only file, because... to react to the importer dock, it has to be an "importable" format. So the idea would be to introduce a filetype and custom importer, which will import as a TextureSet.
PackedTextureImporter
and PackedTextureArrayImporter
, which would import textures from descriptor files listing the channel operations and other options. Then TextureSet
would be able to reference the resulting textures. This would be very nice for re-usability and simplicity of each part, but unmanageable because of the next point...4: if I rely on the import system, it means I have to:
TextureSet
resource after the user clicks "import". Otherwise, doing something like textures.add(load(path))
would just fail because import either failed or did not happen yet. Right now I can trigger a full scan, but I have no guarantee as to when I'll be able to call load
to add the texture in the list...TextureSet
, which sucks for re-usability and API simplicity. Otherwise, it means I can't automate this step to users.Bonus 1: I did the math, and if someone makes a game with terrains having 16 2K PBR textures on them (and it happened), the required space in the project can quickly go above 1 Gb, just from PNG files. Godot's TextureArray
importer holds all images im memory uncompressed, TWICE (once for the input, once for slicing that big atlas it wants), so you better have lots of RAM to spare while importing... unless I take the opportunity to implement the importer differently (what about the loading of that resource tho?? time will tell...).
Bonus 2: the LOSSY compression mode (which just saves files with the WEBP format) is missing for texture arrays, and WEBP is missing from the script API, so I won't be able to make it available. A lost opportunity to lower this big amount of data...
The alternative is to not import, and just generate PNGs, then reverse-engineer .import
files. It's also dirty, but not as bad, and I did this already with terrain data.
Downside is:
Conclusion:
I wasted two nights on this so I'll make a pause there... I need to figure out what to do from here, because it appears what I wanted to do is impossible, not with extra steps from the user (crazy, right)... I would really like to get the design from my previous post though... the "correct" way Godot is exposing feels very limiting.
Update: I've been working hard to overcome some of the issues I had earlier, and I managed to get this feature working in the end, with a few differences from the initial proposal.
The feature is available to test in the texture_sets
branch, along with new documentation https://github.com/Zylann/godot_heightmap_plugin/blob/texture_sets/addons/zylann.hterrain/doc/main.md#texturing
This is now in master.
This is an upcoming feature I'd like to expose before I merge it. Texture sets would be a new custom resource to setup terrain textures, replacing the old way.
Existing system
So far setting up textures for the ground was up to the user, as explained here: https://github.com/Zylann/godot_heightmap_plugin/blob/master/addons/zylann.hterrain/doc/main.md#texturing
If you used a classic shader, you had to make 4 pairs of textures that are each packed like this:
You had to do this packing yourself in an image editor, or using a separate plugin.
If you used an array-based shader, you had to not only do that, but also assemble all your textures in an atlas, and use the default TextureArray importer of Godot, which is impractical and time consuming (also you better have lots of RAM to spare).
Proposal
HTerrainTextureSet
will be a new resource that can hold a collection of terrain textures. It lets you define source images (albedo, bump, normal, roughness), and allows to import them into the kind of texture the plugin expects. This way, you won't need to use an external tool anymore, and changing one of the source images is a lot simpler in the case of texture arrays.Each
HTerrain
node will start with one of these resources by default, and once you choose the data directory, it will be saved next to thedata.hterrain
resource, as a simple.tres
file. The generated textures will then be saved in the same place, either as.stex
or.texarr
. In this workflow, source images may not be used by the game, so it will be possible to place them in a folder with a.gdignore
file, so they won't bloat the exported build. This leads to the following folder organization:Note: because it behaves like a regular resource, it is also possible to re-use the same pre-made set of textures for multiple terrains, by assigning it in the inspector.
Interface
There will be a custom interface to configure a
HTerrainTextureSet
, which can be shown either by inspecting the.tres
resource, or with a shortcut from the terrain editor (double-click on any texture slot, or chooseEdit...
).Work-in-progress:
Other options may also include default values for non-filled slots, normalmap strength to allow using DX convention from CC0Textures, and a mode to switch between texture arrays and individual textures, depending on the shader you are using.