Planetary Rendering - A very basic beginning

Published August 12, 2016
Advertisement

As I may have recently mentioned, I've suddenly become obsessed with the idea of procedural planetary rendering. Maybe it's all the hype surrounding "No Man's Sky" but whatever is causing it, I'm stuck with the idea now.

So it seems there isn't a "SAMS Teach Yourself Planetary Rendering in 24 Hours" available on the internet. I'm obviously going to have to put some actual effort in here. I've been researching as widely as I can, reading all sorts of scary papers and failing miserably to understand them, so I've decided to start with the basics and figure this out myself.

Following along with this fascinating post, I've stolen some of the code in order to recursively generate a sphere based on an icosahedron. I've simplified things a lot for now - no level of detail going on, just a routine to generate the sphere to a given depth of recursion.

Here's the basic routines for this:

void addVertex(const Vec3 &p, const Vec3 &n, VertexBuffer &buffer){ buffer.add(ColorVertex(p, n, makeColor(0, 255, 0)));}void addTriangle(const Vec3 &a, const Vec3 &b, const Vec3 &c, VertexBuffer &buffer){ addVertex(a, normalizeVector(a), buffer); addVertex(b, normalizeVector(b), buffer); addVertex(c, normalizeVector(c), buffer);}void addRecursive(const Vec3 &a, const Vec3 &b, const Vec3 &c, float radius, int depth, int maxDepth, VertexBuffer &buffer){ if(depth == maxDepth) { addTriangle(a * radius, b * radius, c * radius, buffer); return; } Vec3 edgeCenter[3] = { (a + b) / 2, (b + c) / 2, (c + a) / 2 }; Vec3 pos[6] = { a, b, c, edgeCenter[0], edgeCenter[1], edgeCenter[2] }; uint indices[12] = { 0, 3, 5, 5, 3, 4, 3, 1, 4, 5, 4, 2 }; for(uint i = 0; i < 4; ++i) { uint i1 = indices[3 * i + 0]; uint i2 = indices[3 * i + 1]; uint i3 = indices[3 * i + 2]; addRecursive(normalizeVector(pos[i1]), normalizeVector(pos[i2]), normalizeVector(pos[i3]), radius, depth + 1, maxDepth, buffer); }}void makeIcosahedron(float radius, int maxDepth, VertexBuffer &buffer){ float t = (1.0f + sqrt(5.0f)) / 2.0f; pod_vector pos = { { -1, t, 0 }, { 1, t, 0 }, { -1, -t, 0 }, { 1, -t, 0 }, { 0, -1, t }, { 0, 1, t }, { 0, -1, -t }, { 0, 1, -t }, { t, 0, -1 }, { t, 0, 1 }, { -t, 0, -1 }, { -t, 0, 1 }, }; pod_vector indices = { 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 }; for(uint i = 0; i < indices.size() / 3; ++i) { addRecursive(normalizeVector(pos[indices[i * 3 + 0]]), normalizeVector(pos[indices[i * 3 + 1]]), normalizeVector(pos[indices[i * 3 + 2]]), radius, 1, maxDepth, buffer); }}This is all hosted inside the aborted spaceship game I was writing, so I have a nice starfield skybox set up already. I can specify a depth value to the makeIcosahedron routine to generate a sphere at different levels of detail.

Depth = 1 (a basic icosahedron)

depth1.jpg

Depth = 3

depth3.jpg

Depth = 6

depth6.jpg

So this is a reasonable start. What I intend to do next is to start playing around with varying the level of detail on each triangle based on some metrics related to the triangle's position in view space. I'm thinking about starting the addRecursive function by transforming the three coordinates into view space, then culling out any backward facing triangles for a start. Then I can start thinking about/researching ways to decide on the level of detail for the visible triangles.

For now, I'm going to just regenerate the entire buffer every frame, but I'm sure this won't work in the longer term. I just need to take all this stuff one small step at a time and make sure I am completely comfortable with each stage before I move on.

Mountains to climb here but its a fascinating area.

Thanks for stopping by.

Previous Entry Ah
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement