Jump to content
  • Advertisement
Sign in to follow this  
SpreeTree

Procedural Texture Generation

This topic is 4096 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I'm looking for some good resources regarding procedural generation of textures to map on natural object (for example grass, rock or sand etc.). I'm currently using Perlin noise too generate my landscape but I don't think that will cut it here (especially as I require tile-able images) I know Google exists so I'm hoping some of you can point me to any of your favourite sites on the topic or something off the beaten track. ;) Thanks Spree

Share this post


Link to post
Share on other sites
Advertisement
Texturing & Modeling: A Procedural Approach - For terrains, rocks, and various natural looking textures. Your bible if you're serious about procedural techniques.

Algorithmic Botany - Modeling plants and other biological structures. There is some really cool stuff on there.

An Introduction to Lindenmayer Systems - Basic overview of L-Systems which is a fundamental part of generating plants.

Terraform - Tools to generate terrains.

libnoise - A comprehensive library that allows you to generate all sort of procedural stuff, especially textures and terrains.


p.s. You can make tileable Perlin noise. If the texture (or terrain grid) resolution is 2^n, you can create a mask, m = 2^n - 1, where 0 < m <= 255. You can use m to mask the values returned from the permutation table, thus limiting the noise period. Using the reference Perlin noise as an example:


// Note m = 2^n - 1, where 0 < m <= 255. m must never exceed 255, because the permutation table has only 256 entries.
// Texture resolution is assumed to be 2^n.

static public double noise(double x, double y, double z, int m) {
int X = (int)Math.floor(x) & 255, // FIND UNIT CUBE THAT
Y = (int)Math.floor(y) & 255, // CONTAINS POINT.
Z = (int)Math.floor(z) & 255;
x -= Math.floor(x); // FIND RELATIVE X,Y,Z
y -= Math.floor(y); // OF POINT IN CUBE.
z -= Math.floor(z);
double u = fade(x), // COMPUTE FADE CURVES
v = fade(y), // FOR EACH OF X,Y,Z.
w = fade(z);
int A = (p[X ]+Y) & m, AA = (p[A]+Z) & m, AB = (p[A+1]+Z) & m, // HASH COORDINATES OF
B = (p[X+1]+Y) & m, BA = (p+Z) & m, BB = (p[B+1]+Z) & m; // THE 8 CUBE CORNERS,

return lerp(w, lerp(v, lerp(u, grad((p[AA ]) & m, x , y , z ), // AND ADD
grad((p[BA ]) & m, x-1, y , z )), // BLENDED
lerp(u, grad((p[AB ]) & m, x , y-1, z ), // RESULTS
grad((p[BB ]) & m, x-1, y-1, z ))),// FROM 8
lerp(v, lerp(u, grad((p[AA+1]) & m, x , y , z-1 ), // CORNERS
grad((p[BA+1]) & m, x-1, y , z-1 )), // OF CUBE
lerp(u, grad((p[AB+1]) & m, x , y-1, z-1 ),
grad((p[BB+1]) & m, x-1, y-1, z-1 ))));
}




Now, I haven't compiled nor tested this particular code, so it might be broken. However I used a similar approach for my implementation a while back.

Also note the above code assumes your texture is a square or a cube (if you generate 3D noise). If the texture is rectangular (or a 3D brick), you will need to specify m for each dimension separately.

edit: There some other limitations you need to keep in mind with this approach. For example, if you generate multi-octave Perlin noise, you can only increase the octave sampling frequency by multiples of 2, 4, 8, etc.

[Edited by - Tachikoma on March 17, 2007 9:55:44 PM]

Share this post


Link to post
Share on other sites
Excellent, that was exactly what I was looking for.

The libNoise library looks excellent, and I'll def. look into the book you recommended.

I had seen reference to tile-able Perlin noise, but it wasn;t something I had fully looked into. Using perlin noise like that might be a nice way to generate nice texture blends throughout the terrain.

Thanks again :)

Spree

Share this post


Link to post
Share on other sites
If you're interested in reference code, I'd highly recommend downloading the POV-Ray source. The documentation provides a quite detailed description of how the techniques work from a mathematical point of view, and the code is pretty straightforward. As a bonus, you can also visualize the results of various procedural textures directly in POV-Ray.

Share this post


Link to post
Share on other sites
How would I go about tiling noise from libnoise? Will I need to edit the source to take into account this modification? I can't find anything on tiling libnoise's output elsewhere, but I presume this is a fairly common thing to want to do.

Share this post


Link to post
Share on other sites
noiseutils (semi undocumented part of libnoise) provides a seamless texture making function, but it appears this is done as an image operation, not a part of the procedural basis. Consequently the seamless version loses some of the visual quality of the original - it seems messier and blurrier. This reduction in high frequency detail likely results from a mirror-and-add tiling method.

If the output from that is good enough for your needs then great, otherwise you'll have to change the generators [depressed]

I'm pretty sure noiseutils comes with libnoise. If you have any trouble finding the tiling stuff though, let me know. I've probably still got the my code from when I was playing with it.

Share this post


Link to post
Share on other sites
EDIT: ignore the stuff below, immediately after writing it I searched the source for 'seam' and found what I was looking for - utils::NoiseMapBuilderPlane::EnableSeamless. Thanks very much for your help :)



I noticed utils::RendererImage::EnableWrap(), and have enabled it, but it doesn't appear to be working. The documentation says:

"This object requires five points (the initial point and its four neighbors) to calculate light shading. If wrapping is enabled, and the initial point is on the edge of the noise map, the appropriate neighbors that lie outside of the noise map will "wrap" to the opposite side(s) of the noise map. Otherwise, the appropriate neighbors are cropped to the edge of the noise map."

I'm not entirely sure what it's referring to though - 5 points of what? Where do I set them?

Have I got the right method, and if so how do I use it?

Thanks for your help, by the way!

Share this post


Link to post
Share on other sites
cool, glad you found it. I remembered it being a bit obscure. Hope it does what you need. Should be OK for noise, but looks crappy for voronoi.

happy to help [smile]

Share this post


Link to post
Share on other sites
Would libnoise be fast enough to include it in a realtime renderer? I am interested in creating (large) terrains with this library at runtime. If it's slower than a few milliseconds for creating an area of terrain, it would be too slow :-(.
Why realtime? - Well, creating things realtime you do not have to load large amounts from hdd and you only have the currently scene in your RAM.

Share this post


Link to post
Share on other sites
Quote:
Original post by rotalever
Would libnoise be fast enough to include it in a realtime renderer? I am interested in creating (large) terrains with this library at runtime. If it's slower than a few milliseconds for creating an area of terrain, it would be too slow :-(.
Why realtime? - Well, creating things realtime you do not have to load large amounts from hdd and you only have the currently scene in your RAM.

Hi rotalever,

It would depend on how complex your noise is. Using a single Perlin noise module would be fast enough for real-time generation on a recent PC. By the time you add a bunch of additional noise modules, modifiers, selectors, etc., things would really slow down.

There's a way to almost double the speed of the noise generation. If you compile libnoise yourself, open the noisegen.cpp file, go to the GradientCoherentNoise3D() function and change these lines:


// Create a unit-length cube aligned along an integer boundary. This
// surrounds the input point.
int x0 = (int)floor (x);
int x1 = x0 + 1;
int y0 = (int)floor (y);
int y1 = y0 + 1;
int z0 = (int)floor (z);
int z1 = z0 + 1;


to


// Create a unit-length cube aligned along an integer boundary. This
// surrounds the input point.
int x0 = (x > 0.0? (int)x: (int)x - 1);
int x1 = x0 + 1;
int y0 = (y > 0.0? (int)y: (int)y - 1);
int y1 = y0 + 1;
int z0 = (z > 0.0? (int)z: (int)z - 1);
int z1 = z0 + 1;


For whatever reason, the floor() calls are very slow. Casting to an int and doing a conditional produces the same result, but at a much faster speed.

Currently, I've got this change in the libnoise CVS, but it's not yet in the downloadable build. Once sufficiently tested, this change will be included in the next version.

Quote:
Original post by mrbastard
cool, glad you found it. I remembered it being a bit obscure. Hope it does what you need. Should be OK for noise, but looks crappy for voronoi.

Is there a way to improve the voronoi noise?

-- jas

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!