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

Gltf loader reads texCoord field of texture #13153

Closed

Conversation

bugsweeper
Copy link
Contributor

Objective

Solution

Gltf loader reads texCoord field of each texture except lightmap, when finds TEXCOORD_n with same index n selects ATTRIBUTE_UV_0, otherwise (in case of lightmap) selects ATTRIBUTE_UV_1. This workaround according to the way bevy_pbr uses uv attributes

@bugsweeper
Copy link
Contributor Author

This workaround doesn't work if textures depend on different texCoords, for example #13086. Full correct solution includes change bevy_pbr to use (or abble to use) different ATTRIBUTE_UV_n for each texture. @alice-i-cecile Do we want to dig so deep?

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen A-Assets Load files from disk to use for things like images, models, and sounds labels Apr 30, 2024
@alice-i-cecile
Copy link
Member

I'm personally okay with this as a partial fix, but obviously a full fix would be valuable down the line. Actually following the gltF spec is valuable, and this is a reasonable and useful part of it, but there's no need to block a 90% solution IMO.

@superdump @IceSentry @robtfm, as SME-Rendering I think this decision is up to you.

@robtfm
Copy link
Contributor

robtfm commented May 2, 2024

apologies if i misunderstood something - it looks like this approach will apply (from the texcoords you've added to the hashmap) whichever is specified last in the mesh primitive. that sounds like it is probably worse than assuming texcoord(0).

i expect meshes which use multiple distinct uvs will normally have the base texture uv coords first, so in those cases we will be using the wrong coords for the base color texture (where previously we would use the wrong coords for metallic/occlusion/normals).

i think it would be better if the HashSet was an Option that stored the most important use, then we could choose to use the most appropriate coords (if base color texture exists, map the relevant texcoords to UV_0. otherwise if normal map exists map those, else metallic else occlusion etc).

@bugsweeper
Copy link
Contributor Author

bugsweeper commented May 2, 2024

that sounds like it is probably worse than assuming texcoord(0)

As I mentioned earlier this workaround doesn't work in all cases, correct solution is to use separate uv_map for each texture. HashSet doesn't keep single value, it keeps all of them.
Let's try to describe situation more thoroughly. Lets imagine example when there is two textures (base color and occlusion). What happen depending on texCoord values (numbers of UV maps)?

texCoord values Behavior before changes Behavior after changes
Both are 0 Correct Correct
Values don't match Incorrect Incorrect
Values match but not 0 Incorrect Correct

Do you think that if mesh uses baseColorUV instead of normalUV for normal texture, the mesh will look correct?

@robtfm
Copy link
Contributor

robtfm commented May 2, 2024

Do you think that if mesh uses baseColorUV instead of normalUV for normal texture, the mesh will look correct?

no, but i think errors in occlusion map uvs or normal map uvs are probably less noticeable than errors in base color texture uvs... and those features can be disabled, so it's still possible to get something close to correct, if not fully-featured.

how about, use an option to record what uvs we are going to take (starting from most important), and then if the uv is already chosen, discard lower-priority textures that don't use the same?

so if base color texture uses texcoords(0) and normal map uses texcoord(1), don't add the normal texture and use texcoord 0.
if normals use texcoord(1) and occlusion uses texcoord(0), don't add occlusion and use texcoord 1.
etc

@robtfm
Copy link
Contributor

robtfm commented May 2, 2024

one issue with my suggestion is that gltfs might use multiple identical sets of texcoords, in which case it would currently be working but would lose features with this strategy. i don't know if that's common.

@robtfm
Copy link
Contributor

robtfm commented May 2, 2024

HashSet doesn't keep single value, it keeps all of them.

(just wanted to point out that while the hashset has all of them, only one ATTRIBUTE_UV_0 can exist on the final mesh. the code would repeatedly overwrite the mesh attribute so finally the uvs would be whichever was specified last in the gltf.)

@bugsweeper
Copy link
Contributor Author

bugsweeper commented May 3, 2024

@robtfm Looks like there is alternate PR which already fixes even #13086 , which my solution is not supposed to fix.

github-merge-queue bot pushed a commit that referenced this pull request May 13, 2024
# Objective

- The StandardMaterial always uses ATTRIBUTE_UV_0 for each texture
except lightmap. This is not flexible enough for a lot of gltf Files.
- Fixes #12496
- Fixes #13086
- Fixes #13122
- Closes #13153

## Solution

- The StandardMaterial gets extended for each texture by an UvChannel
enum. It defaults to Uv0 but can also be set to Uv1.
- The gltf loader now handles the texcoord information. If the texcoord
is not supported it creates a warning.
- It uses StandardMaterial shader defs to define which attribute to use.

## Testing

This fixes #12496 for example:

![wall_fixed](https://github.com/bevyengine/bevy/assets/688816/bc37c9e1-72ba-4e59-b092-5ee10dade603)

For testing of all kind of textures I used the TextureTransformMultiTest
from
https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/TextureTransformMultiTest
Its purpose is to test multiple texture transfroms but it is also a good
test for different texcoords.
It also shows the issue with emission #13133.

Before:

![TextureTransformMultiTest_main](https://github.com/bevyengine/bevy/assets/688816/aa701d04-5a3f-4df1-a65f-fc770ab6f4ab)

After:

![TextureTransformMultiTest_texcoord](https://github.com/bevyengine/bevy/assets/688816/c3f91943-b830-4068-990f-e4f2c97771ee)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior
Projects
None yet
3 participants