godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add a way to combine PBR maps into an ORM texture for use in ORMMaterial3D #2316

Open Calinou opened 3 years ago

Calinou commented 3 years ago

Describe the project you are working on

The Godot editor :slightly_smiling_face:

Describe the problem or limitation you are having in your project

Creating StandardMaterial3Ds for use in Godot requires a lot of clicks. A full PBR material typically requires 5 or 6 different texture maps:

ORMMaterial3D improves this by only requiring 3 textures for most materials (4 if you need height or emission), but you need specially crafted ORM maps. Most websites distributing PBR materials such as CC0Textures only provide separate texture maps, not ORM maps.

Another upside of using ORM maps is that they are slightly more optimized compared to using separate texture maps, and can also be compressed in a more efficient way. Lastly, since you have less files lying around in your 3D library, it makes folders easier to browse :slightly_smiling_face:

ORM maps (for Occlusion, Roughness, Metallic) contain the AO map in the red channel, the roughness map in the green channel and the metallic map in the blue channel.

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

Add a tool in the editor to convert a set of 3 textures into a single ORM map. This would be a one-way operation. By default, the original texture maps would be kept but there could be a checkbox to remove them automatically once the operation has succeeded.

Additionally, the tool can save a .tres ORMMaterial3D resource next to the textures. This would further speed up material setup.

I don't think we can provide this feature in the Import dock since there won't be a 1:1 mapping between a source PBR map and the "final" ORM map.

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

A dedicated dialog could be provided in the Project > Tools menu:

image

Here's a mockup made with Excalidraw:

image Source: orm-material-converter-mockup.excalidraw.zip

The only required field is Albedo. All other fields will be guessed automatically, but material conversion should be functional even if only the Albedo slot is filled in. Guessing textures is based on commonly used naming pattern globs, such as {basename}*normal* for normal maps, {basename}*ao* for ambient occlusion, and so on (case-insensitive). {basename} is the name of the albedo map with the albedo*/diffuse*/basecolor* suffix, file extension and trailing dash/underscore removed.

The following name patterns can be used for guessing:

The above list only mentions {basename}_snake_case naming conventions, but {basename}_PascalCase, {basename}PascalCase and {basename}-kebab-case would be automatically attempted as well.

To reduce UI complexity for new users, I suggest disabling all fields other than Albedo until an albedo texture has been specified.

The placeholder texts will change once an albedo texture has been specified. If no texture could be guessed for a given slot, the placeholder will change to (no [slot] texture found) instead (e.g. (no emission texture found)).

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

This can be achieved through external programs (ImageMagick can do this in an automated way), but it's not particularly convenient, especially for people not familiar with the command line.

The following ImageMagick command can be used to combine an ambient occlusion, roughness and metallic map into a single ORM map:

convert ao.png roughness.png metallic.png -combine orm.png

To separate them back to separate maps:

convert orm.png -channel R -separate ao.png && convert orm.png -channel G -separate roughness.png && convert orm.png -channel B -separate metallic.png

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

See above.

Jummit commented 3 years ago

Tbh, my gut feeling says this should either be done with an external program or using a plugin, so I made one: https://github.com/Jummit/channel-packer screenshot

clayjohn commented 3 years ago

I think @Zylann also has a nice plugin to pack textures!

NHodgesVFX commented 3 years ago

I think @Zylann also has a nice plugin to pack textures!

https://github.com/Zylann/godot_channel_packer_plugin although it hasn't been updated in a while not sure if it still works

Zylann commented 3 years ago

@NHodgesVFX did you try it? Last time I checked there was an issue with the window layout due to hi-DPI displays or different font sizes (which was always an issue with almost every plugin)

Also I havent updated it in a while because the need became even more complicated when I started using texture arrays, so I implemented texture packing by creating a custom importer for a custom file format listing the packing instructions, combined with a tool to edit such files because importer dock UI sucks, which then led to this https://github.com/godotengine/godot-proposals/issues/1943

NHodgesVFX commented 3 years ago

Tbh, my gut feeling says this should either be done with an external program or using a plugin, so I made one: https://github.com/Jummit/channel-packer screenshot

what happens if you have 4k+ textures and want to keep them that size or if you want to pack something into the alpha. otherwise looks good

Calinou commented 3 years ago

@NHodgesVFX @Jummit The add-on should probably detect the size of all 3 textures and use the largest size for the final image. This way, the user won't have to specify the size manually and it'll work for non-square textures too.

NHodgesVFX commented 3 years ago

@NHodgesVFX did you try it? Last time I checked there was an issue with the window layout due to hi-DPI displays or different font sizes (which was always an issue with almost every plugin)

Just tried it, seems to have a couple issues.

  1. I couldn't find it at first top right corner is not the best place perhaps project-> tools would be better.
  2. I couldn't drag connect the points it doesn't seem to be working. So i used a preset
  3. the texture exported but didn't reimport into Godot for some reason.
  4. the dialog should probably be closed after the texture is saved
Zylann commented 3 years ago

I couldn't drag connect the points it doesn't seem to be working. So i used a preset

I never implemented this part because it was actually created in response to a need in my terrain plugin, so using presets was faster, while the connected points are only illustrative.

the texture exported but didn't reimport into Godot for some reason.

This is a problem I keep running into so I opened this: https://github.com/godotengine/godot-proposals/issues/1615

alexfreyre commented 3 years ago

would be great if the images to be imported has some prefix in the name and Godot convert the three images on import process, let's say

resulting in godot automatically:

Godot can evaluate this on import so is up to the user if he wants to use the "tool" in any moment or to import the images directly with the prefix

Calinou commented 3 years ago

@alexfreyre The issue is that there is no 1:1 mapping between an AO/roughness/metallic texture and an ORM texture. It's a 3:1 mapping, and the Godot import system isn't designed to deal with that.

alexfreyre commented 3 years ago

the Godot import system isn't designed to deal with that.

I mean that at import time, the import system could ideally detect the prefixes and then ask for the tool (of this PR) you want to create, then the tool do the combination to get automatically the 3:1 orm.

Either way this ends, it will be a great feature.