An algorithm for tiling any n-dimensional texture function in 2+ dimensions

Greets :slight_smile:

As someone who’s worked with textures, particularly with the intent of creating games, I keep finding myself wanting to be able to get tiling versions of Blender’s textures (perlin noise, clouds, etc).

One thing I noticed early on is that it’s pretty easy to make a texture that tiles in one dimension – all you have to do is create a cylinder, assign a surface texture, and then bake that texture to an image. Since the texture is actually in 3D space, the texture image will wrap perfectly along the X dimension, but unfortunately it doesn’t wrap along the Y dimension. So I got to wondering if there was some shape I could create that would have this property in both directions. The only obvious choice is a torus, but unfortunately if put a torus in 3D space and then unwrap a baked planar texture from it, you end up with weird stretching and compressing because the texture plane isn’t distributed evenly over it, so that’s not going to work.

Consider, for a moment, what happens mathematically when you put a cylinder into a 3D texture space and then bake the texture plane. Essentially what you’re doing is taking the X coordinate of the 2D (x, y) texture space, and mapping that to an x and z coordinate of 3D texture space, and leaving the y coordinate the same. The mapping is extremely simple. x maps to x=sin(x) and z=cos(x), so the texture plane wraps around the 3d area in a circle, making it repeat along one axis. So for an (x, y) point on the plane, the corresponding point in space is (sin(x), y, cos(x)).

Now, this is kind of difficult to comprehend because our minds aren’t meant to think in 4 dimensions… but, if we’re wrapping our plane in four dimensions, it’s possible for a 4D object to exist that wraps like a cylinder on both axes, without stretching the plane the way a torus would. Without breaking our brains trying to imagine what such a shape might look like, just think of the math. Your 2D (x, y) point in texture space would map to a point in 4D space as: (sin(x), cos(x), sin(y), cos(y)). So what you end up with is a smooth, continuous loop of both X and Y in 2D space.

The cool thing here is that you can apply this method to any texture that can be made 4 dimensional. My own test implementation uses Perlin Simplex noise:

http://oga2.opengameart.org/tilenoise/

I’ve borrowed the simplex noise code from a paper that I credit on the page above. My own code, which accomplished the above algorithm, is very brief, but it proves that it works. Note that the texture drawn on the HTML canvas repeats in both directions and doesn’t look funny at all. You could easily modify the code to produce different tiling textures.

Furthermore, you can tile textures in more than two dimensions using the same general idea. For an N-dimensional tiling texture, the texture generation function needs to generate the texture in (2*N) dimensions. So you can use it to create a repeating 3D texture, a repeating 2D texture that morphs over time and returns to its original state without ping-pong-ing, or a 3D texture that does the same.

As a side note, some people might point out that perlin noise already tiles – this is true, but you have to iterate over all of the noise to get it to tile, which means that you’re very limited in terms of the character of the texture if you do it this way. My method gets around this by allowing you to combine arbitrary textures in arbitrary ways and have them all tile over some distance that you can specify yourself.

Anyway, I’d like to get a feel for how interested people would be in seeing this kind of capability in Blender. I feel like this kind of feature would go along way toward making Blender be able to compete with a lot of expensive texture editing software (since Blender’s texture and material node editors are already very robust). I’d love to see this added in as an option for textures where it makes sense, allowing the user to tile the texture over an arbitrary distance in one, two, three, or four dimensions.

Peace,
Bart K.
http://opengameart.org

P.S. Maybe I should draw a diagram of what I’m getting it? I feel like the concept may be a little confusing.

P.P.S. Apologies if such an algorithm is already known and was invented before by someone else. If it exists, I wasn’t able to find it on google. :slight_smile:

well would like to see a built having this new feature for texture in 2.5
would be great feature texture tilable!

now meanwhile is there a scripts available for the different textures?

that we can use in 2.5?

thanks and a happy 2.5

That’s very cool. I’ve never heard of that technique before.

I’m not sure how easily it would fit into Blender though. Is there a workflow for generating texture images?

sweet idea!
i (almost) never looked into blender’s code, but two ideas:

either one would have to hack in another mapping type that does take care of that.
or all procedural textures get a “tileable” option.

this way one could bake out those noises in a tileable way.

however, you might as well give this one a try for now:
http://www.mapzoneeditor.com/

Regarding a workflow for creating 2d procedural textures in Blender:

  • Create a 1x1 square
  • Position an orthographic camera to look straight down at it.
  • Get rid of all your light sources and turn environmental lighting up to full white ( rgb(1, 1, 1) )
  • Edit the square’s texture and material in the node editor.
  • Bake the various components of the texture (diffuse, specular, normal map, whatever) and save the baked result.
  • Note: It’s been a while since I did this, so my steps may be a little wrong, but that’s the idea. :slight_smile:

Blender is actually a really excellent node-based texture editor for games. What’s particularly funny about it is that that’s not its primary purpose, but the node texture and material system is very robust and works quite well for that purpose. It’s certainly the best open source texture editor I’ve come across.

As for how to make all these textures tileable, I’d be most in favor of giving a tileable option to all of them. Creating a set of separate, tileable textures would work, but would be silly from a UI standpoint. Anyway, if Blender is going to be a single stop program for creating games, this would be a really handy feature. Obviously for rendered content it’s not such a big deal, although I imagine it might be helpful from time to time.

As for the technique, it’s possible that other people are using it, but I haven’t seen anyone write about it. There’s a commercial texture generator program out there that generates seamlessly tiled perlin noise, but they don’t explain how they do it. It could be they’re doing it the same way… regardless, I searched google for this idea and I didn’t find it anywhere, so it’s possible that it may be completely original. :slight_smile:

Bart

hmm, i was kinda bored and curious today, so i fiddled around in blender’s sources.

the first solution you mentioned, where it would tile only in one dimension wasn’t that hard. i altered the texture mapping function texco_mapping in texture.c:

from:

texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]);
texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]);
texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]);

to:


texvec[0] = mtex->size[0]*sin(3.14159265*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]));
texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]);
texvec[2] = mtex->size[2]*cos(3.14159265*(mtex->projz ? (co[mtex->projx - 1] + mtex->ofs[2]) : mtex->ofs[2]));

result (with voronio; but works with all of them):
http://openmuffin.net/stuff/blender2.jpg
as you can see, it tiles in X only, not in Y.

the second version that would generate a fully tileable 2D texture however is much harder to do, since as far as i saw blender’s procedural noises are all three dimensional only, whereas you would need a 4 dimensional noise. now i’m not a math guy at all, so correct me if i’m wrong.

anyways, it is doable, but i’m afraid i’m not capable of doing this within reasonable time since i’m not experienced enough. also ton or a core dev should evaluate this and decide if and how it should be implemented.

@lendrick:
afaik you don’t need to position a camera or change/remove lights to bake textures.

It would seem that for Voronoi you would have to generate the cells so if one went over an edge, the rest of the cell would be generated on the other side of the tile.

I’m not experienced with texture lingo, but think of the procedural noise as a certain shape (a simple noise primitive) and think of the detailed texture consisting of thousands of them of all different sizes, now generate a thin border of noise at the tile’s edges with half on one side and the other half wrapped to the other side so if you tiled it then you have seamless tiling with a noisy border and black inside of that, now take that data and generate from that noise to fill in the rest of the tile. Maybe start with a wrapped border of cells for voronoi then fill the rest of the tiles with cells in a way they would fit.

I have never coded a texture, but I know MapZone generates procedural noise based on simple generated shapes duplicated and scaled by the thousands (If you ever worked with the advanced settings, I don’t know if Blender’s textures work the same way though)