4
\$\begingroup\$

I am writing a planet renderer and have stumbled into a problem that I cannot solve. I am generating heightmaps in a glsl pixel shader. These heightmaps are generated for every quad in the quadtree that the planetary sphere is built on. The sphere is a cube transformed by the equations found here. The way I am generating a point to be inputted into the noise function in the shader is shown here:

vec2 coords = vec2((gl_FragCoord.x - 0.5) * m_Scale , (gl_FragCoord.y - 0.5) * m_Scale)+m_Offset;
vec2 position = vec2(coords.x,coords.y);
vec3 noiseInput;

 if(m_t == 1){

 noiseInput = vec3(spherize(vec3(position.x, 0.0, position.y) + m_faceOffset))/m_worldSize;
}else if(m_t == 2){

noiseInput = vec3(spherize(vec3(position.x, position.y, 0.0) +  m_faceOffset))/m_worldSize;

}else if(m_t == 3){

noiseInput = vec3(spherize(vec3(0.0, position.x, position.y) +   m_faceOffset))/m_worldSize;

}

Here "m_Scale" is the length of the quad's edges divided by the lengths of one of the root node's sides. m_Offset is a variable which offsets the quad from the origin. m_worldSize represents the planet's radius. m_faceOffset is the variable which translates the quad to it's correct face of the cube (faceIndex = faceOffset):

if(c.face.equals(faces.TOP)){
                    c.faceIndex = new Vector3f(nhsize, hsize, nhsize);
                }else if(c.face.equals(faces.BOTTOM)){
                    c.faceIndex = new Vector3f(nhsize, nhsize, nhsize);
                }else if(c.face.equals(faces.FRONT)){
                    c.faceIndex = new Vector3f(nhsize, nhsize, hsize);
                }else if(c.face.equals(faces.BACK)){
                    c.faceIndex = new Vector3f(nhsize, nhsize, nhsize);
                }else if(c.face.equals(faces.RIGHT)){
                    c.faceIndex = new Vector3f(hsize, nhsize, nhsize);
                }else{
                    c.faceIndex = new Vector3f(nhsize, nhsize, nhsize);
                }

where hsize is the radius of the planet and nhsize is the radius negated. Finally, m_t describes which face of the cube the quad is supposed to be on:

if(q.face.equals(QuadMesh.faces.TOP.toString()) || q.face.equals(QuadMesh.faces.BOTTOM.toString())){
                    t = 1;
                    }
                if(q.face.equals(QuadMesh.faces.FRONT.toString()) || q.face.equals(QuadMesh.faces.BACK.toString())){
                    t = 2;
                    }
                if(q.face.equals(QuadMesh.faces.RIGHT.toString()) || q.face.equals(QuadMesh.faces.LEFT.toString())){
                    t = 3;
                    }

"spherize" is the function which transforms a point on the cube to a point on the sphere:

     denom1 = hWorldSize * hWorldSize * 2f;
 denom2 = hWorldSize * hWorldSize * hWorldSize *hWorldSize * 3f;

     vec3 spherize(vec3 v){
float x = (v.x * (sqrt(1.0-((v.y*v.y)/m_denom1)-((v.z*v.z)/m_denom1)+(((v.y*v.y)*(v.z*v.z))/m_denom2))));
float y = (v.y * (sqrt(1.0-((v.x*v.x)/m_denom1)-((v.z*v.z)/m_denom1)+(((v.x*v.x)*(v.z*v.z))/m_denom2))));
float z = (v.z * (sqrt(1.0-((v.y*v.y)/m_denom1)-((v.x*v.x)/m_denom1)+(((v.y*v.y)*(v.x*v.x))/m_denom2))));
return vec3(x,y,z);
 }

This all leads to the following problem:

enter image description here

As one can see the faces of the "cube" do not match up. I am at a loss here; I use the exact same methods described above to transform the vertices of the cube to those of a sphere.

Any and all help is highly appreciated. If one needs more code to form an accurate opinion please let me know.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ You're using a 2D noise function? If you use a 3D one and just put in the position on the sphere's surface, this problem will go away. Otherwise, you'll have to do some surgery on the internals of the noise function, or blend together multiple noise invocations. \$\endgroup\$ Dec 15 '13 at 9:03
  • \$\begingroup\$ I am using 3D noise. I cannot use a point on the sphere's surface as input since the heightmaps are generated separately from the vertices of the planet. \$\endgroup\$ Dec 15 '13 at 16:25
  • 1
    \$\begingroup\$ OK, you're generating the heightmaps in a pre-pass, but you know where they will be applied on the sphere right? You can work out what the 3D position on the sphere will eventually be. \$\endgroup\$ Dec 15 '13 at 18:10
  • \$\begingroup\$ Well I attempt to simulate this in the above code. I generate the "vertices" as if I was generating them for the geometry, I offset to place them on the correct face like I do for the vertices on the sphere, and I use the same mapping equation that I use for the vertices on the sphere. I am not sure what the problem is though... Also, if I did have the vertices for the quad I am not sure how I would pass those to the pixel shader that creates the height map. \$\endgroup\$ Dec 15 '13 at 18:36
  • \$\begingroup\$ Nathan said exactly what I would have said. I also think this is the track to follow. For your "passing to px shader" problem, you need to re-calculate in the pixel shader itself, no passing involved. just the varying available from your vertex shader should give you an interpolated position in your quad that will be the input of your spherical mapping projection. \$\endgroup\$
    – v.oddou
    Dec 17 '13 at 3:03
0
\$\begingroup\$

I ended up going with the suggestions above and used the position of the sphere as the input to the noise...I did this by recalculating the sphere position in the vertex shader for the height map texture:

vec3 varPos = vec3(inPosition.xyz);
varPos *= m_Size;

if(m_t == 1){
vec3 v1 = vec3(varPos.x, 0.0, varPos.y);
vec3 v2 = v1 + m_faceOffset;
vec3 v3 = v2 + m_meshOffset;
spherePos = spherize(v3);
}else if(m_t == 2){
vec3 v1 = vec3(varPos.x, varPos.y, 0.0);
vec3 v2 = v1 + m_faceOffset;
vec3 v3 = v2 + m_meshOffset;
spherePos = spherize(v3);
}else if(m_t == 3){
vec3 v1 = vec3(0.0, varPos.x, varPos.y);
vec3 v2 = v1 + m_faceOffset;
vec3 v3 = v2 + m_meshOffset;
spherePos = spherize(v3);
}

Thanks for the help!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.