Open tobloef opened 1 year ago
Can you reproduce this when exporting a .gltf file and importing it in Godot? (Godot internally tells Blender to export a .gltf file.)
This may be a bug in Blender's glTF exporter, especially if you can't reproduce this with another tool that exports glTF files.
When exporting a .gltf file from Blender and importing it in Godot, I get a combined Metallic/Roughness texture file. This is loaded into the material correctly as the two textures are indeed the same file, just different channels.
I assume this "combine into one texture" behavior is the intention for the .blend import as well?
As an aside, I personally find it somewhat unintuitive that the textures are automatically combined instead of just using the two image textures I set up in Blender. I wonder, what's the reason for this being the default?
I assume this "combine into one texture" behavior is the intention for the .blend import as well?
Yes; I don't know why it's not happening when Godot imports a .blend
file directly.
As an aside, I personally find it somewhat unintuitive that the textures are automatically combined instead of just using the two image textures I set up in Blender. I wonder, what's the reason for this being the default?
Using this approach results in better performance (fewer textures need to be used for the material), as you can use ORMMaterial3D instead of StandardMaterial3D. See also https://github.com/godotengine/godot-proposals/issues/2955.
Using this approach results in better performance (fewer textures need to be used for the material), as you can use ORMMaterial3D instead of StandardMaterial3D. See also godotengine/godot-proposals#2955.
Makes sense. Do you know if it's possible to disable this behavior? I can't seem to find something like that in the import settings. If not, that's totally fine. It's not what this issue is about anyway π
Regarding the actual issue, if someone could point me to the right corner of the codebase I would also be happy to look into the issue myself.
Makes sense. Do you know if it's possible to disable this behavior?
Not that I know of.
Regarding the actual issue, if someone could point me to the right corner of the codebase I would also be happy to look into the issue myself.
The Blender importer code is here: https://github.com/godotengine/godot/blob/ec62b8a3ee1d731387a440b4d2abb7961aa28322/modules/gltf/editor/editor_import_blend_runner.cpp
As you can see, Godot executes Blender with a specific Python payload designed to make it export a glTF file.
I have been looking into this more over the weekend. This will be a somewhat long post with the details of my findings. I hope it can serve as a jumping-off point for any potential fixes.
Forgive me if some of this is obvious to veterans of the engine, I'm a very recent immigrant from the Unity fiasco. If you have corrections, please let me know!
Blender has 3 main modes of exporting gLTF files: Binary
(.glb), Embedded
(.gltf), and Separate
(.gltf + .bin + textures).
Note that by default, whether using embedded textures or not, Blender will combine the Metallic and Roughness into the texture we previously talked about in this thread. It is possible to disable this behavior by toggling the Keep original
option when using the Separate
mode, but this does come with the following very relevant warning:
β οΈ If you use more than one texture, where PBR requires only one, only one texture will be used. This can lead to unexpected results.
When importing a .blend file, Godot will behind the scenes call Blender and perform a gLTF export, just like Calinou said. This export uses the Separate
mode, along with Keep original
set to True
.
To me, this explains the faulty behavior originally described in this issue. Godot seemingly assumes that the Metallic and Roughness textures will be combined, while explicitly telling Blender not to do that.
So perhaps we can solve the issue by changing export settings. The table below shows the results of importing gLTF files manually exported from Blender, both for projects where the texture files have and have not been packed into the .blend file.
Packed | Unpacked | |
---|---|---|
Binary | β β | β |
Embedded | β β | β |
Separate | β β‘ | β β‘ |
Separate + Keep original | β | β |
Legend
β Imported with Metallic and Roughness correctly assigned
β Imported with Metallic incorrectly assigned to the same texture file as Roughness
β If Godot's Embedded Image Handling
is set to Extract Textures
in the scene import settings, you will have to trigger a second import. Otherwise, the imported scene will error due to missing images. I believe this to be a bug.
β‘ You of course have to import the exported textures and the .bin file alongside the .gltf file, as they are not embedded inside the project with this export setting.
At this point, I thought the fix would be to simply change Godot's Blender export settings to one of the working formats from the table above. This can be easily done here: https://github.com/godotengine/godot/blob/6de34fde27f650f738a1e46992f1b783f2cf9e76/modules/gltf/editor/editor_scene_importer_blend.cpp#L77-L78
However, all approaches I tried had issues.
Separate
and Embedded
For Separate
and Embedded
exports, the scene has no Metallic/Roughness textures assigned at all and Godot produces the following error:
π΄ Can't find file 'res://.godot/imported/Unpacked-ef043bcaf77b3602acfd1d86d08410e3_Metallic-Roughness.png'.
π΄ No loader found for resource: res://.godot/imported/Unpacked-ef043bcaf77b3602acfd1d86d08410e3_Metallic-Roughness.png (expected type: Texture2D)
π‘ modules/gltf/gltf_document.cpp:3233 - glTF: Image index '0' couldn't be loaded with the name: Metallic-Roughness. Skipping it.
After the import has run, .godot/imported
will actually contain the combined Metallic/Roughness texture in question, but Godot will not import it due to it being in the .godot
folder. I assume this is on purpose to prevent an infinite loop:https://github.com/godotengine/godot/blob/7aff59f0b6920b970454c7608148845619d6cd60/editor/editor_file_system.cpp#L1369-L1371
Additionally, if the Blender project is not packed and you import the textures as well, .godot/imported
will also contain a combined Metallic-Roughness.png
texture. Note that this will happen despite the export mode being Embedded
. There will also be the following error in the log:
π΄ No loader found for resource: res://.godot/imported/Metallic-Roughness.png (expected type: )
Binary
For both packed and unpacked Blender files, the imported scene will completely fail and get a little β icon. The following will be printed in the log:
π΄ modules/gltf/gltf_document.cpp:7580 - Condition "err != OK" is true. Returning: ERR_FILE_CANT_OPEN
π΄ Error importing 'res://Unpacked.blend'.
Barring abandoning the issue, I see two potential actions to take from here:
A) Make Godot support importing gLTF files with separate textures for Metallic and Roughness. This would help not only with gLTF support in general but also allow the existing Blender file importing to Just Workβ’.
B) Figure out what goes wrong when Godot uses other export settings in the Blender import process. With this, Godot would not have to concern itself with separate Metallic/Roughness textures, as they would be combined during the Blender export.
I'm not sure either of these fixes would be easy for me to execute, but I would be willing to take a look if we knew what approach we wanted to go with. I'm also very open to someone more experienced with the engine taking it from here.
If you've read all this, I thank you. I would love to hear what you think. Perhaps someone would be willing to see if they get similar results and that it's not just me messing something up.
Cheers βοΈ
glTF does not support separate textures for metal and roughness, they have to be combined into one texture. (Same for base color and alpha.)
glTF does not support separate textures for metal and roughness, they have to be combined into one texture. (Same for base color and alpha.)
Makes sense. So something like approach B from my previous post (quoted below) would be the way to go?
B) Figure out what goes wrong when Godot uses other export settings in the Blender import process. With this, Godot would not have to concern itself with separate Metallic/Roughness textures, as they would be combined during the Blender export.
(I've updated the wording in the wording slightly, to not emphasize using Binary
mode for the export)
@tobloef As an aside, I personally find it somewhat unintuitive that the textures are automatically combined instead of just using the two image textures I set up in Blender. I wonder, what's the reason for this being the default?
This happens because glTF does not support specifying different textures for metallic as roughness, it specifies only a metallicRoughnessTexture
for both: https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/schema/material.pbrMetallicRoughness.schema.json#L43 Therefore, "A) Make Godot support importing gLTF files with separate textures for Metallic and Roughness" is not possible. ...uh, sorry, I missed the last part of the discussion where this was mentioned already, but I'll keep this text around instead of deleting it in case the details and link helps.
Anyway, it seems that Blender does not have a way to "unpack" the converted roughness+metallic texture. I've made two PRs to fix this problem: #96778 and #96782. However, note that you will need to uncheck this box:
Reproducible in Godot v4.3.stable and Blender 4.1.1/4.2.2 Here's the model i use to test: The Cartoon Knight_anim.zip
Godot version
v4.1.1.stable.official [bd6af8e0e]
System information
Godot v4.1.1.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3070 (NVIDIA; 31.0.15.3713) - AMD Ryzen 7 5800X 8-Core Processor (16 Threads)
Issue description
When importing .blend files, the Roughness texture is used for both the Roughness and the Metallic properties of the imported material. I would expect the imported model to use the Metallic texture that was set up in Blender.
Steps to reproduce
In Blender (3.6.3):
In Godot (4.1.1):
Minimal reproduction project
Godot project: MetallicImportBugRepro_Godot.zip
Blender project: MetallicImportBugRepro_Blender.zip