Skip to content

WIP: Position-based texture variants proof-of-concept #16027

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

kno10
Copy link
Contributor

@kno10 kno10 commented Apr 14, 2025

This PR is based on #13811, add node texture variants.
The majority of the changes comes from the branch!

But instead of using param2, it uses hash(pos) % variants_count to choose the texture variant.

Before, note the alignment pattern in the grass left of the birch tree:
screenshot_20250414_210436

After, grass textures randomly rotated:
screenshot_20250414_210759

It is possible to use completely different textures as variants. These examples simply used ^[transformR90 etc.

It depends on the textures how well this works. Dirt looks okay, but for example these stone textures have a direction to them:

screenshot_20250414_212058

before:
screenshot_20250414_212128

Doing just two variants (^[transformR180) works better for these textures:
screenshot_20250414_212436

So looking forward to having multiple texture variants for brick walls, mossy brick walls, etc.!

@kno10
Copy link
Contributor Author

kno10 commented Apr 14, 2025

Ping @ryvnf as you may like this.
Ping @sfence who did most of the work on variants after picking up TurkeyMcMac's work (thanks!)

@kromka-chleba
Copy link
Contributor

What's the difference between this and world-aligned textures? (looks useful, I'd just like to know the difference though)
With world-aligned textures you can define a seamless 128x128 px texture with scale 8 which can fit a grid of 8x8 nodes with textures 16x16 px.

@cx384
Copy link
Contributor

cx384 commented Apr 14, 2025

It is similar to the align_style feature, but with random textures (depending on the position) and arbitrary number of variants.

I like this feature, but would prefer it to be implemented as part of the Tile definition.
(This way, it may also be possible to use it and param2 dependent textures at the same time.)
I heard that people do not like it when the same node placed at different positions looks different, but at least for me this is no problem.

(TurkeyMcMac will not receive your ping https://forum.luanti.org/viewtopic.php?t=29161)

@kno10
Copy link
Contributor Author

kno10 commented Apr 14, 2025

They do not repeat "exactly" after every 8 nodes, either. I think the difference is most noticeable if you have a large, flat surface of one node.
I did not know about world-aligned textures with scale, seems like an interesting alternative.

This implementation does combine with param2 coloring, for example! The grass above has param2 color.

@kno10
Copy link
Contributor Author

kno10 commented Apr 14, 2025

Same node, but two different param2 colors (two different biomes) for the bushy leaves.
Additional variation due to textures being randomly rotated using the variants method in this pull (which doesn't overload the param2, as it is only using the node position).
screenshot_20250414_222838

and with blocky leaves, where tiling matters much more:
screenshot_20250414_223253

@kromka-chleba
Copy link
Contributor

Well, world-aligned textures still do repeat even if they're seamless.
Would be nice to get something that can scramble seamless textures across entire mapblocks.
Something like this solution in Blender: https://www.youtube.com/watch?v=-VgtSL5ZpYc

@kno10
Copy link
Contributor Author

kno10 commented Apr 14, 2025

@kromka-chleba actually @HybridDog has worked on something much more advanced, Stochastic texture sampling:
#2746 (comment) and https://forum.luanti.org/viewtopic.php?t=30600

@Zughy Zughy added Textures Feature ✨ PRs that add or enhance a feature Concept approved Approved by a core dev: PRs welcomed! @ Server / Client / Env. labels Apr 14, 2025
@cx384
Copy link
Contributor

cx384 commented Apr 14, 2025

This implementation does combine with param2 coloring, for example! The grass above has param2 color.

I meant the variants param2 feature.
With your implementation, the variants field is either used to change the node appearance depending on param2 or depending on the hashed position if variant_pos = true, right? So you can't use both features for the same node.
In any case, I don't see why it wouldn't be better to make this a part of the Tile definition. But who am I to judge, in my opinion, it should be done for the other variants feature, too. #13811 (comment)

@Zughy Zughy added Roadmap: supported by core dev PR not adhering to the roadmap, yet some core dev decided to take care of it and removed Concept approved Approved by a core dev: PRs welcomed! labels Apr 14, 2025
@kno10
Copy link
Contributor Author

kno10 commented Apr 14, 2025

I think my code currently may actually break the param2 variants, by simply not checking that variant_pos==true yet. ;-)
(I probably should fix this right now, so I do not forget again.)

It would be possible to combine both, but you'd need to specify how the two values interact. So variant_pos would need to be some bitmask, and param2 varianting would need to be another bitmask. One option would be to set variant_pos = 4 to multiply position-based variants by 4, then add param2-based variants. Or they could be additive. I don't know how many users this will ever have, it's probably overengineering.

TurkeyMcMac and others added 2 commits April 15, 2025 06:31
@ryvnf
Copy link
Contributor

ryvnf commented Apr 15, 2025

Nice work!

Considering this is concept approved I will use it instead of the param2 solution for rotated blocks in Mineclonia. It feels so much cleaner without the LBMs and clients will also be able to predict the orientation of placed nodes.

@sfence
Copy link
Contributor

sfence commented Apr 15, 2025

Implementing #15319 sounds like a good alternative to this for me.

@kno10
Copy link
Contributor Author

kno10 commented Apr 15, 2025

Implementing #15319 sounds like a good alternative to this for me.

Honestly, I prefer position-based texture randomization to any param2 hacking by 100x, so much easier to use, and no version compatibility issues.
We still need #15319 just to efficiently set the param2 colors, though. But I am not looking forward to setting both color and texture variations via the biomes mechanism, and having to figure out how to convert old worlds.

@HybridDog

This comment was marked as resolved.

@kno10
Copy link
Contributor Author

kno10 commented Apr 17, 2025

The pseudo-randomly chosen variant repeats every 16 nodes with the current code (commit fa62c59):

I may have trimmed down the randomization code to much - can you try uncommenting some of the lines in

luanti/src/mapnode.cpp

Lines 63 to 64 in fa62c59

//hash *= 0xc2b2ae35;
//hash ^= hash >> 16;

(and above) if this increases randomness. I tried to make it as cheap as possible. I won't have time the next days.

@HybridDog

This comment was marked as resolved.

@kno10
Copy link
Contributor Author

kno10 commented Apr 17, 2025

Maybe the position passed to getVariant() is already in { 0 , 1 , … , 15 } 3 .

Thank you! Makes sense: maybe the position used at that codepath is within a chunk, and hence 0-15.
Given the line below compares to a relative position, p here likely is relative:

tile = f.tiles[mn.getVariant(p, f)][tileindex];

@SmallJoker
Copy link
Member

What's the difference of this PR to world-aligned textures? It seems to me that both attempt to bring texture into the world.

luanti/doc/lua_api.md

Lines 9639 to 9644 in 1c5776d

* `{name="image.png", backface_culling=bool, align_style="node"/"world"/"user", scale=int}`
* backface culling enabled by default for most nodes
* align style determines whether the texture will be rotated with the node
or kept aligned with its surroundings. "user" means that client
setting will be used, similar to `glasslike_framed_optional`.
Note: supported by solid nodes and nodeboxes only.

Added by: #6105 (includes some nice screenshots)
In comparison to this PR, it uses a single (larger) texture and can thus still combine vertices (greedy meshing).

@cx384
Copy link
Contributor

cx384 commented Apr 21, 2025

The crucial difference to world-aligned textures is that it doesn't repeat every 16 nodes, thus more randomness and no repeating patterns. However, in its current implementation this is not the case, and for me to support this feature it would have to be implemented in tile definition, also you should be able to give every texture variant a weight to adjust the randomness.

@kno10
Copy link
Contributor Author

kno10 commented Apr 21, 2025

@SmallJoker: non-repeating patterns by randomization. world-aligned textures repeat if you have larger flat surfaces.
@cx384 @HybridDog: the 16-node pattern caused by relative coordinates is supposedly fixed in 4e59ce5 from 4 days ago by adding the block position, but I have not tested this in more detail yet:

tile = f.tiles[mn.getVariant(p + data->m_blockpos*MAP_BLOCKSIZE, f)][tileindex];

@HybridDog
Copy link
Contributor

It no longer repeats every 16 nodes with version 4e59ce5 in my example.
randomness

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature ✨ PRs that add or enhance a feature Roadmap: supported by core dev PR not adhering to the roadmap, yet some core dev decided to take care of it @ Server / Client / Env. Textures
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants