So I've been making some slow progress with my planet rendering. Hit a bit of a brick wall at the moment so thought it was time to post a quick update on where I have gotten so far.
I was playing around with different noise generation methods and ended up basing one on Sean O'Neil's Sandbox project. Works very nicely.
I cleaned up and refactored the code into my own style and format. Actually fairly compact in the end.
class Noise{public: explicit Noise(unsigned int seed); float noise(const Vec3 &v) const;protected: float lattice(int ix, float fx, int iy=0, float fy=0, int iz=0, float fz=0, int iw=0, float fw=0) const; unsigned char perm[256]; float buffer[256][3];};Noise::Noise(unsigned int seed){ std::srand(seed); for(int i = 0; i < 256; ++i) { perm = i; for(int j = 0; j < 3; ++j) { buffer[j] = (float)random(-0.5, 0.5); } float magnitude = 0; for(int j = 0; j < 3; ++j) { magnitude += buffer[j] * buffer[j]; } magnitude = 1 / sqrtf(magnitude); for(int j = 0; j < 3; ++j) { buffer[j] *= magnitude; } } for(int i = 0; i < 256; ++i) { int j = static_cast(random(0, 255)); std::swap(perm, perm[j]); }}float Noise::noise(const Vec3 &v) const{ int n[3]; float r[3]; float w[3]; for(int i = 0; i < 3; ++i) { n = floor(v); r = v - n; w = cubic(r); } float value = lerp(lerp(lerp(lattice(n[0], r[0], n[1], r[1], n[2], r[2]), lattice(n[0]+1, r[0]-1, n[1], r[1], n[2], r[2]), w[0]), lerp(lattice(n[0], r[0], n[1]+1, r[1]-1, n[2], r[2]), lattice(n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2]), w[0]), w[1]), lerp(lerp(lattice(n[0], r[0], n[1], r[1], n[2]+1, r[2]-1), lattice(n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1), w[0]), lerp(lattice(n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1), lattice(n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1), w[0]), w[1]), w[2]); return clamp(value * 2.0f, -0.99999f, 0.99999f);}float Noise::lattice(int ix, float fx, int iy, float fy, int iz, float fz, int iw, float fw) const{ int n[4] = { ix, iy, iz, iw }; float f[4] = { fx, fy, fz, fw }; int index = 0; for(int i = 0; i < 3; ++i) { index = perm[(index + n) & 0xFF]; } float value = 0; for(int i = 0; i < 3; ++i) { value += buffer[index] * f; } return value;}
Next I moved this into my planet program and used it to set a colour on each of the vertices of the generated sphere.
The problem I have now is that the resolution is limited to the resolution of the sphere. I can't generate the noise inside of a shader, so the only way I can think to move forward now is to use the noise method offline to generate a cubemap and then sample this with the interpolated directional vectors in the pixel shader to spread the noise smoothly across the planet.
Maybe this is how this stuff works, but this means I have to generate the entire planet into a cube map at a fixed maximum resolution. I was hoping there was some way I could sample the noise method as I went along without having to pre-render the results.
Am I missing something obvious here? If I generate a cubemap with 1024x1024 textures say, it imposes quite a strict maximum resolution on my planet surface. How else can I sample the noise method given a directional vector inside the pixel shader?
Stuck. Any tips appreciated.
[EDIT] So I started trying to generate some offline cube maps and hit another brick wall there trying to get them to seamlessly tile.
Maybe if you have time, you could pop by my Plea For Help Thread in Graphics Programming and Theory and offer me some expertise? Thanks :)
[EDIT] Woo hoo, all sorted, was mapping the vectors to the pixels wrong was all:
That's the basic noise with turbulence applied, wrapping seamlessly around a cube. Next up, importing this into the planet renderer and sampling it in the shader :)
Are you sure you can't generate the noise inside of a shader? I'm not a shader guy so I don't really know why that wouldn't be possible.
One idea for you is to use noise hierarchically. Let's say you currently sample per-vertex of the sphere - that's your high-level. At a more local level (let's say per face fragment) you could sample some noise (e.g. from the same or a 2nd noise texture) and composite that on top of the existing (per-vertex) noise. But the point is you sample from the whole texture per-face.
I think ideally you're looking for some way to create a fractal - the more you dig in the more detail there is?