Displacement map on a sphere


#1

Hi,
Anyone knows how to do a displacement map on a sphere using Cinder 0.9+ ?
I had it working Cinder 0.8.6 project I want to update, but I can’t figure out how to use the quads I used back then…


#2

Hi Bruce.

I would probably recommend displacing the vertices of the sphere in a vertex shader. The inbuilt geom::Sphere should have texture coordinate and normal attributes which will allow you to provide a displacement texture to the shader and move the vertices along the normal by the amount at that texel on the sphere.

The only problem with doing the displacement in the vertex shader is that the resulting displaced form wont have the correct normals (unless you calculate and update these in the vertex shader too but this is a little more tricky). It depends whether you are going for a graphical style where the normals wont matter (non shaded) or are looking for a shaded blob.

If you need an accurately shaded sphere then modifying and updating the vertex positions on the CPU (checkout the TriMesh class) and calling recalculateNormals() after moving the vertex positions should give you correct normals for your displaced sphere. This will be a lot more expensive on the CPU side whereas the vertex shader approach is entirely GPU based.

Hope this helps.


#3

You can also construct the normal in the fragment shader:

vec3 DeriveNormalFromHeight( in sampler2D heightMap, in vec3 normal, in vec4 position, in vec2 tc )		      {
    vec3 N = normalize( normal );

    // Perturb normal using height map.
    vec3 sigmaS = dFdx( position.xyz );
    vec3 sigmaT = dFdy( position.xyz );
    vec3 vR1 = cross( sigmaT, N );
    vec3 vR2 = cross( N, sigmaS );
    float fDet = dot( sigmaS, vR1 );
    
    // Find the height derivatives using forward differencing.
    const float kHeightMultiplier = 0.05;
    float h = kHeightMultiplier * texture( heightMap, tc ).x;
    float hs = kHeightMultiplier * texture( heightMap, tc + dFdx( tc ) ).x;
    float ht = kHeightMultiplier * texture( heightMap, tc + dFdy( tc ) ).x;
    float dBs = hs - h;
    float dBt = ht - h;
    vec3 surfGrad = sign( fDet ) * ( dBs * vR1 + dBt * vR2 );

    return normalize( abs( fDet ) * N - surfGrad );
}

-Paul


#4

Hey @brucelane,

Here’s a sample I made quite a while ago, although it’s using an IcosSphere, but it’s using a displacement map to distort the vertices inside the vertex shader, as @felixfaire mentioned, maybe it’ll be helpful: https://github.com/Craigson/Cinder_Samples/tree/master/DisplacementIcos


#5

I will try those different approaches soon, thanks.
@Craigson as I am on Windows, I forked your repo and tryed with VS2017, unfortunately nothing is drawn.
Will try harder…


#6

Hey Bruce, sorry I missed this. I’ll see if I can get it running on a windows system and let you know!