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:

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:

The code for the rotation is here:

1//https://gist.github.com/ayamflow/c06bc0c8a64f985dd431bd0ac5b557cd2//https://www.reddit.com/r/godot/comments/ldqwve/how_to_rotate_each_uv_tile_individualy_in/3 uniform sampler2D tDiffuse;4 varying vec2 vUv;56 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 }1415 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.y19 );20 }212223 void main(void) {24 vec2 uv = vUv * 100.0;2526 vec2 tile = floor(uv);2728 vec2 center = tile + vec2(0.5, 0.5);2930 vec2 randomRotatedTileUV = rotateUV(uv , rand(tile, 2.0)* 200.0, center);3132 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.y5 );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:

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:

## 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 ❤️