godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
87.18k stars 19.59k forks source link

[3.3/3.4b] «2D Pixel» preset glitch in 3D #53883

Open alchem1ster opened 2 years ago

alchem1ster commented 2 years ago

Godot version

both 3.3.4 stable and 3.4 beta 6

System information

Windows 10, GLES3, RTX 2070 Super (472.12)

Issue description

When loading some voxel textures into Godot and applying the "2D Pixel" import preset, texture artefacts occur. It does not depend on the type of model: dae, obj or fbx.

There are no such problems when loading in Blender etc.

Blender: blender

Godot: godot

Steps to reproduce

Import throne sample model from ZIP to Godot project. Apply "2D Pixel" preset to PNG texture, reimport it and apply to model.

Minimal reproduction project

throne.zip Throne_sample.zip

Calinou commented 2 years ago

@alchem1ster Please upload a minimal reproduction project to make this easier to troubleshoot.

The project you uploaded only contains the Collada file and its texture, not a complete Godot project.

alchem1ster commented 2 years ago

Added project sample Throne_sample.zip

Calinou commented 2 years ago

I can confirm this on commit f6784e18d.

image

The wireframe view looks fine:

image

Changing the texture's compression mode to Lossy will reveal that UV mapping is done in a weird way:

image

I'd try using glTF 2.0 over Collada and see if the issue persists. This looks like a 3D import/export issue to me rather than an issue with the texture itself. The texture itself looks like it's correctly imported:

image

alchem1ster commented 2 years ago

@Calinou

I'd try using glTF 2.0

If you mean gltf+bin+textures separately, the problem persists

Calinou commented 2 years ago

If you mean gltf+bin+textures separately, the problem persists

Try triangulating the model before exporting it from the 3D software you're using. This is always more reliable than letting the 3D importer perform the triangulation. In Blender, you can do this by adding a Triangulate modifier and enabling Apply Modifiers in the export dialog. Some exporters such as Blender's OBJ exporter also feature a Triangulate Faces option, but I recommend using a triangulate modifier and applying it on export instead as this lets you preview the triangulation.

This advice isn't exclusive to Godot. It's common practice when working with 3D software such as a Blender -> Substance Painter workflow as well.

alchem1ster commented 2 years ago

Of course. I always do Triangulation and Recalculate Normals. That doesn't seem to be the problem

p.s. Anyway, for some reason the same model is displayed correctly in Blender

scurest commented 2 years ago

This is caused by UV compression. The compressed UVs are not accurate enough in this case. If you untick Meshes>Compress in the Import pane and reimport, it's fixed. I believe Godot uses float16s for UVs? You get a similar (though not identical) effect if you convert all UVs to float16s and back in Blender.

Click to see picture ![Blender shows similar effect after going through half-floats](https://user-images.githubusercontent.com/11024420/137599993-aca6bad1-f529-4c63-bb0e-46a5124fdaf9.png)

Aside:

Try triangulating the model before exporting it from the 3D software you're using. This is always more reliable than letting the 3D importer perform the triangulation.

For the Blender glTF exporter, this is not true, you should always let the exporter triangulate for you. It will export the triangulation that Blender actually draws. You should not apply a triangulate modifier, it will not give you the right triangulation.

alchem1ster commented 2 years ago

@scurest

If you untick Meshes>Compress in the Import pane and reimport, it's fixed

Nope :/

Godot screenshot ![godot_disable_compress](https://user-images.githubusercontent.com/3815426/137601587-18448138-dc52-43e4-ad9d-bca636c1bd26.png)
scurest commented 2 years ago

After hitting reimport, double click on untitled.gltf and do "New Inherited" again. Works for me on 3.3.4 stable.

alchem1ster commented 2 years ago

Confirmed, but..

3.3.4 stable:

3.4 b6:

3.3.4 stable:

So, if doing Reimport in 3.3.4 stable all seems to be good. But something wrong in 3.4.

Calinou commented 2 years ago

This is likely a regression from https://github.com/godotengine/godot/pull/46800. I think there's an option to disable mesh compression in the 3D scene's import options.

alchem1ster commented 2 years ago

But why doesn't it fix objects that are already in the scene after pressing the Reimport button? To remove the artefacts I need to either remove the object from the scene and add it again, or create a child inherited scene for it. But what if I have hundreds of objects in the GridMap?

akien-mga commented 2 years ago

This is likely a regression from #46800. I think there's an option to disable mesh compression in the 3D scene's import options.

CC @The-O-King

lyuma commented 2 years ago

I saw this PR wasn't merged: https://github.com/godotengine/godot/pull/48625

Is the special import setting still needed? or was that PR obsoleted by something else?

The-O-King commented 2 years ago

So yea this has to do with the UV coordinate compression

I updated PR #48625 to resolve merge conflicts as I think it would a valuable feature to have, being able to more granularly control what attributes are/are not compressed - so that in this case you could enable compression on everything except UV coordinates vs having to either disable ALL compression because one attribute didn't play nice with compression

When I was testing things I was able to import/reimport the .dae file with/without UV compression and that fixed the issues seen here

As for the behavior of Godot when reimporting - I think that's been Godot's behavior for this type of thing for a while

  1. If you imported an asset as a scene (lets call this scene A) and then merged a mesh from the asset's scene into a new scene (lets call this scene B), the mesh in the new scene (B) is essentially detached from the scene created directly from the asset (A), so reimporting will not effect it at all, it's stuck using whatever the import setting was at the time of merging

  2. if you import an asset as a scene (lets call it scene A) and then use that scene as a node in a new scene (lets call this one scene B), reimporting WILL affect the node in scene B but only after opening and closing the scene

Is my understanding of the scene behavior correct here?

akien-mga commented 2 years ago

Tested and the issue is still reproducible in 3.5 beta 5.

As discussed above by @The-O-King, it's related to UV coordinate compression. I found that disabling Meshes > Compress > TexUV and reimporting the DAE is sufficient to solve this issue:

image

@The-O-King Can/should we consider that this is working as intended and that this is a kind of mesh where the user needs to disable compression explicitly? Or can the importer be clever about it and automatically disable compression when it detects cases like this where it might be problematic?

The-O-King commented 2 years ago

So right now, yes I believe everything is working as intended, as this is just a precision issue with compression the UV coordinates to an insufficient precision level for the texture coordinates used by this mesh

As for whether or not we can detect this automatically and disable as needed, that's a good question; my initial instinct would be that we would check the delta between what the compressed UV coordinates is and the ground truth UV coordinate is during import, and if that delta is larger than some threshold; we print a warning to the log letting the user know that it might be good to try reimporting this mesh without compression if they see any rendering artifacts (or perhaps we can restart the import automatically, not sure what would be preferred)

I can investigate a feature like this if that sounds like a good solution to this problem!