Skip to content

Fix texture coordinates of cuboid drawtypes#16091

Merged
SmallJoker merged 5 commits into
luanti-org:masterfrom
cx384:fix_texture_coords
May 24, 2025
Merged

Fix texture coordinates of cuboid drawtypes#16091
SmallJoker merged 5 commits into
luanti-org:masterfrom
cx384:fix_texture_coords

Conversation

@cx384

@cx384 cx384 commented Apr 27, 2025

Copy link
Copy Markdown
Member

To do

Ready for review

How to test

See that texture coordinates are correct,
align style and other texture coordinates features like rotation still work.
and check nodebox drawtype nodes.

@cx384
cx384 force-pushed the fix_texture_coords branch from c6c5e80 to a64a314 Compare April 27, 2025 16:29
@cx384
cx384 marked this pull request as ready for review April 27, 2025 16:33
break;
case TileRotation::R270:
tcoords.set(tcoords.Y, -tcoords.X);
tcoords.set(tcoords.Y, 1 - tcoords.X);

@cx384 cx384 Apr 27, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subtracting from 1 here is always correct, since even for texture coordinates from oversized nodeboxes, it stays aligned to the [0,1] range, and always has scale 1.
(visual_scale changes the mesh scale and not the texture coords scale.)
So we are not subtracting from the corresponding entry in txc.

Comment thread src/client/content_mapblock.cpp
Comment thread src/client/content_mapblock.cpp Outdated
@sfan5
sfan5 self-requested a review April 29, 2025 14:29
Co-authored-by: sfan5 <sfan5@live.de>
@sfan5

sfan5 commented May 3, 2025

Copy link
Copy Markdown
Member

to check UV coords:

diff --git a/src/client/meshgen/collector.cpp b/src/client/meshgen/collector.cpp
--- a/src/client/meshgen/collector.cpp
+++ b/src/client/meshgen/collector.cpp
@@ -25,8 +25,9 @@ void MeshCollector::append(const TileLayer &layer, const video::S3DVertex *verti
 
        u32 vertex_count = p.vertices.size();
        for (u32 i = 0; i < numVertices; i++) {
+               v2f uv{core::clamp(vertices[i].TCoords.X, 0.f, 1.f), core::clamp(vertices[i].TCoords.Y, 0.f, 1.f)};
                p.vertices.emplace_back(vertices[i].Pos + offset, vertices[i].Normal,
-                               vertices[i].Color, vertices[i].TCoords);
+                               vertices[i].Color, uv);
                m_bounding_radius_sq = std::max(m_bounding_radius_sq,
                                (vertices[i].Pos - m_center_pos).getLengthSQ());
        }

@sfan5

sfan5 commented May 3, 2025

Copy link
Copy Markdown
Member

world-aligned coords have shifted by one node, but the new one is actually aligned properly:
screenshot_20250503_110624
^ old | new v
screenshot_20250503_110849

@sfan5 sfan5 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked:

  • world-aligned nodes
  • facedir
  • nodeboxes
  • gromit test mod from #12266

}

tcoords.set(x * scale_factor, y * scale_factor);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could probably be generalized by performing maths on the normal vector of the tile (do we have that?) but whatever

@Desour Desour left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glasslike_framed is broken. (Also uses drawAutoLightedCuboid and expects nodebox-like uv.)

Found no issues otherwise (also tested with tileable_vertical, it works now. 🎉 ). Thanks!

Comment thread src/client/content_mapblock.cpp Outdated
assert(tilecount >= 1 && tilecount <= 6); // pre-condition

auto vertices = setupCuboidVertices(box, txc, tiles, tilecount);
auto vertices = setupCuboidVertices(box, txc, tiles, tilecount, cur_node.p);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw. you could easily fix scale being limited to int fractions of 16 (currently it's mesh chunk size dependent then), by adding blockpos_nodes here. (Maybe follow up PR.)

@cx384

cx384 commented May 3, 2025

Copy link
Copy Markdown
Member Author

Oh, I must have thought that glasslike_framed is just a normal node mesh, should be fixed now.

Co-authored-by: DS <ds.desour@proton.me>
Comment thread src/client/content_mapblock.h Outdated
@grorp

grorp commented May 3, 2025

Copy link
Copy Markdown
Member

Some meshgen tests were added in #13616. Would testing the texture coordinates there be possible?

also tested with tileable_vertical, it works now. 🎉

Hmm, it doesn't seem to be working for me, Devtest "Dirt with Snow" still appears to use repeat instead of clamp. With texture filtering enabled, and texture_min_size disabled by source code change (also visible without, but this makes it much more obvious):

dirt with snow in devtest

core.register_node("basenodes:dirt_with_snow", {
description = "Dirt with Snow",
tiles ={"basenodes_dirt_with_snow.png",
-- a little dot on the bottom to distinguish it from dirt
"default_dirt.png^basenodes_dirt_with_snow_bottom.png",
{name = "default_dirt.png^default_snow_side.png",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
})

(Feel free to consider things out of scope.)

@cx384

cx384 commented May 3, 2025

Copy link
Copy Markdown
Member Author

Maybe, I'm not very familiar with our unittests.
I suppose it would be a bit much for this PR, it can always be added later, and if we add tests it should probably be done for all draw types, not only cuboids.

I haven't looked into tileable_vertical and tileable_horizontal maybe Desour knows.
With this PR, texture coordinates are inside the [0,1] range, so at least tiles that have not wrap mode GL_REPEAT should not be completely broken.

@grorp

grorp commented May 3, 2025

Copy link
Copy Markdown
Member

Maybe, I'm not very familiar with our unittests.
I suppose it would be a bit much for this PR, it can always be added later, and if we add tests it should probably be done for all draw types, not only cuboids.

Some unit tests are better than no unit tests :)
But yeah, it's fair if you want to consider that out of scope for this PR.

I haven't looked into tileable_vertical and tileable_horizontal maybe Desour knows.
With this PR, texture coordinates are inside the [0,1] range, so at least tiles that have not wrap mode GL_REPEAT should not be completely broken.

Yeah, this is definitely a step in the right direction to get that working.
I think the remaining brokenness might only apply to "solid" nodes because the code for them just overrides the tile material flags:

getTile(tile_dirs[face], &tiles[face]);
for (auto &layer : tiles[face].layers) {
if (backface_culling)
layer.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
layer.material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;
layer.material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;

Presumably this was done as a hacky fix for everything turning broken with tileable_vertical/horizontal=false, and is no longer needed after the fixes in this PR. (The flags are regularly set here:

luanti/src/nodedef.cpp

Lines 696 to 705 in 486fb7c

// Material flags
layer->material_flags = 0;
if (backface_culling)
layer->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
if (tiledef.animation.type != TAT_NONE)
layer->material_flags |= MATERIAL_FLAG_ANIMATION;
if (tiledef.tileable_horizontal)
layer->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;
if (tiledef.tileable_vertical)
layer->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;

)

EDIT: looks like I was right :)
#6903 (comment)
d80d2c8
(later merged as #13216)

@sfan5

sfan5 commented May 4, 2025

Copy link
Copy Markdown
Member

While unit testing meshgen is good I think we would also benefit from having a static scene that can be rendered in CI and the screenshot compared to a known good snapshot.

@Desour

Desour commented May 4, 2025

Copy link
Copy Markdown
Member

also tested with tileable_vertical, it works now. 🎉

Hmm, it doesn't seem to be working for me

I meant that it doesn't completely break nodes anymore.
But yes it's force-disabled for solid nodes. (I should know this, but I completely forgot it. x))

Fixing this can also be done in another PR. 🤷

Unittests would of course always be nice. I approve anyways.

@Desour

Desour commented May 4, 2025

Copy link
Copy Markdown
Member

I found a small issue: glasslike used to just take the lower 1/scale portion of the texture, now it uses the whole texture.
In practice I think this only matters for glasslike_framed_optional when you want to use world aligned with scale frames (does anyone do this? x)), and want to have a proper fallback for normal glasslike.

It would be nice if we could also properly support glasslike and flowingliquid, and the shiny part of glasslike_framed.

@sfan5 sfan5 added this to the 5.13.0 milestone May 4, 2025
@sfan5

sfan5 commented May 4, 2025

Copy link
Copy Markdown
Member

Adding to next release due to high-risk bug fix (IMO).

@cx384

cx384 commented May 5, 2025

Copy link
Copy Markdown
Member Author

According to our documentation, align_style is only supported for solid nodes and nodeboxes, not sure if glasslike and glasslike_framed count as solid. And scale is documented to work for world-aligned textures only.

If I'm not wrong, according to our code, glasslike does not support align_style and it also did not support it before this PR. So I guess it is safe to assume that glasslike_framed_optional does not support it, even if glasslike_framed (maybe undocumented) does. If we want to it change it, better support align_style for glasslike nodes, instead of introducing a fallback. To be honest, glasslike_framed_optional gets rarely used and align_style even more rarely. Those two combined is very unlikely, so it's probably not worth supporting for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Combining animated & world-aligned textures has alignment issues.

6 participants