Hello fellow game programmers,
I'm currently working on a planet rendering application.
I am using the famous 6 quadtree method, where each face is made of an adaptive quadtree.
I'm using only one VBO for the grid and around 8 IBOs for stitching the chunks of different LOD.
The problem i'm currently having is that whenever i get close to the surface everything starts to jiggle so i assume that i'm having some floating point precision issues.
The thing is, i can't find a way out of this. My planets are really huge (Earth huge) and i don't want to give up on that.
These are the steps that i'm following to create my planet:
1. Create a cube out of 6 grids (the grids are managed by the quadtree)
2. The GPU rotates, scales and translates the chunks and then normalizes everything to inflate the cube into a sphere
3. Multiply the vertex with the scale matrix to get it to the desired size.
I believe the problem is with scaling the children chunks
For instance, if the size of the root chunk is 6371000.0, it's children are scaled down to 3185500.0 and translated to NW, NE, SE and SW.
Maybe for the ground level chunks, the size is so small that floats start going crazy.
Vertex Shader code.
vec3 roundChunkVertex = normalize((r_ChunkTransform * vec4(r_Vertex, 1.0)).xyz);
gl_Position = r_Camera * r_Scale * vec4(roundChunkVertex, 1.0);
r_ChunkTransform is a matrix that rotates, translates and scales the chunk.
r_ChunkTransform = R * T * S;
Where R is the rotation matrix.
switch (side)
{
case TS_TOP:
R = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
break;
case TS_BOTTOM:
R = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f));
break;
case TS_LEFT:
R = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f));
break;
case TS_RIGHT:
R = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break;
case TS_FRONT:
R = glm::rotate(glm::mat4(1.0f), glm::radians(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break;
case TS_BACK:
R = glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
break;
}
T is the translation matrix that "offsets" the chunk within it's parent.
glm::dmat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(offset, 0.0f));
S scales the grid on the x and y axes.
glm::dmat4 S = glm::scale(glm::mat4(1.0f), glm::vec3(scalar, scalar, 1.0f));
This is the split function
void TerrainNode::split()
{
this->leaf[NW] = new TerrainNode(this, side, NW, glm::vec2(-.5, 0.5) * (float)scalar + offset, radius, scalar / 2.0);
this->leaf[NE] = new TerrainNode(this, side, NE, glm::vec2(0.5, 0.5) * (float)scalar + offset, radius, scalar / 2.0);
this->leaf[SE] = new TerrainNode(this, side, SE, glm::vec2(0.5, -.5) * (float)scalar + offset, radius, scalar / 2.0);
this->leaf[SW] = new TerrainNode(this, side, SW, glm::vec2(-.5, -.5) * (float)scalar + offset, radius, scalar / 2.0);
this->isSplit = true;
}
I attached a screenshot of the issue.
Thank you.