Planet Generation - continued

Published August 17, 2016
Advertisement

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.

perlin.jpg

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.


planet.jpg

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:

cubemap.jpg

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 :)

4 likes 4 comments

Comments

dmatter

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?

August 17, 2016 07:00 PM
Aardvajk

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?


It might be possible to generate the noise in the shader. I'm not sure.

I'm currently just trying to generate an offline cubemap using noise but can't seem to get seamlessness working :) One stumbling block at a time, eh?
August 17, 2016 07:59 PM
Mak

If you're looking for resolution independent, you're best off looking to generate noise in the shader - which can be done easily by the way. In fact, you can repurpose the code you have already and lift it in. Using the shader as the workhorse eliminates most of the concerns with texture seams, especially when using 3D noise.

I've yet to get around to completing my article on Dominium's planetary terrain system, but here is a link to Acko's superb resource I used as a reference; http://acko.net/blog/making-worlds-introduction/

August 19, 2016 07:11 PM
Aardvajk

If you're looking for resolution independent, you're best off looking to generate noise in the shader - which can be done easily by the way. In fact, you can repurpose the code you have already and lift it in. Using the shader as the workhorse eliminates most of the concerns with texture seams, especially when using 3D noise.

I've yet to get around to completing my article on Dominium's planetary terrain system, but here is a link to Acko's superb resource I used as a reference; http://acko.net/blog/making-worlds-introduction/


Thanks for the response and the link. I'll check it out later. I've been thinking more about noise in the shader and yes, I agree it should be possible. I'm then a bit confused though about how I get access to the height values on the CPU side for doing, say, walking on the terrain and so on.

But keep any tips, links, hits etc coming. I've had a tough time finding clear resources on the subject, which keeps it fun but frustrating at times.
August 20, 2016 07:24 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement