FDNavigate back to the homepage

Mosaic Tiling With Semi Seamless Textures in a R3F or Threejs Setting

Rick
January 12th, 2022 · 2 min read

So instead of using blenders shader node graph to bake a texture into an image, this time we are exploring texturing using a seamless texture effectively.

Here is the codesandbox:

When you tile textures, even seamless textures, I bet your eyes would be very good at detecting patterns..

For example below shows a tiled texture which is just texturing a large plane in R3F:

Seamless texture before rotating uv's

As you can see 👀 there is an obvious pattern, which you could argue if the plane wasnt so big it wouldnt be as noticeable. The keen eyed among you will notice this isnt really a truely seamless texture.

Even if you did use one, your eyes or brains are experts in detecting patterns.

So how can you over come this?

I found this technique while playing around with blender and watching several tutorials.

Mosaic rotation!

This implementation is probably not strictly this technique in the truest sense, but it trys to mimic it.

Below is a general diagram of what is invovled here:

Architecture behind the technique or mosaic rotation

The code for the rotation is here:

1//https://gist.github.com/ayamflow/c06bc0c8a64f985dd431bd0ac5b557cd
2//https://www.reddit.com/r/godot/comments/ldqwve/how_to_rotate_each_uv_tile_individualy_in/
3 uniform sampler2D tDiffuse;
4 varying vec2 vUv;
5
6 float rand(vec2 co, float seed) {
7 float a = 12.9898;
8 float b = 78.233;
9 float c = 43758.5453;
10 float dt= dot(co.xy ,vec2(a,b));
11 float sn= mod(dt, 3.14);
12 return fract(sin(sn + seed) * c);
13 }
14
15 vec2 rotateUV(vec2 uv, float rotation, vec2 mid) {
16 return vec2(
17 cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
18 cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
19 );
20 }
21
22
23 void main(void) {
24 vec2 uv = vUv * 100.0;
25
26 vec2 tile = floor(uv);
27
28 vec2 center = tile + vec2(0.5, 0.5);
29
30 vec2 randomRotatedTileUV = rotateUV(uv , rand(tile, 2.0)* 200.0, center);
31
32 gl_FragColor = texture2D(tDiffuse, randomRotatedTileUV);
33 }

First off the UV’s are from 0-1 so we want lots of tiles so we need to do this to scale it up:

1vec2 uv = vUv * 100.0;

Dont forget as we have done this:

1texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

The texture will never run out so to say.

Next we get the floor of every uv such that:

1floor(vec2(1.123, 1.45)) == vec2(1.0,1.0)

we can basically ensures that for every tile we can then determine the center by adding:

1vec2(1.0, 1.0) + vec2(0.5, 0.5);

Then we can rotate every UV for a tile around its center by using this function:

1vec2 rotateUV(vec2 uv, float rotation, vec2 mid) {
2 return vec2(
3 cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
4 cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
5 );
6}

Nope I didnt come up with this, it was on a very useful gist here.

I literally googled rotate uvs gist. You’d be suprised at how many useful things you’ll find by just adding the word gist to the end of google search 😂

This allows us to use the uv’s a vec2 input, an angle input and a pivot point input to rotate around. The pivot point is the center of each tile or there abouts!

This bit:

1rand(tile, 2.0)* 200.0

The key thing is using the vec2 tile which is this:

1floor(uv);

Why?

Well we want the angle to be the same for each uv in the same tile, otherwise you get this:

Random angle for every uv weird result

And flooring every uv in a given tile will result in whole numbers and more importantly the same whole number for every uv in a single tile.

And this is the end result:

End result of mosaic rotation of a seamless tiled texture

Final Thoughts

This has been my experience of trying to implement moasic rotation to avoid repeating patterns while using seamless textures. It might not all be 100% accurate but will give you a good spring board to researching and playing around with it yourself…

So this is an interesting effect or technique and you could go further with this and add noise to avoid any weirdness at the edges when zoomed in.

Thanks for tuning in, next time will be more blender nodes and models ❤️

More articles from theFrontDev

Height Dependant Node Based Shader Baked to a Textures for GLTF models

Using blenders shader graph to generate a height dependant mixture of two textures and then baking this to a texture for use in a GLTF Model.

January 4th, 2022 · 3 min read

Bloom and Chaining Effect Composers, Whilst Using Three's Layers

Bloom effect using R3F, three's layers and chaining effect composers. The end result being merging two renders into one and giving selective bloom.

December 30th, 2021 · 2 min read
© 2021–2024 theFrontDev
Link to $https://twitter.com/TheFrontDevLink to $https://github.com/Richard-ThompsonLink to $https://www.linkedin.com/in/richard-thompson-248ba3111/