I am trying to create an asteroid by applying a displacement map with perlin noise to a sphere. Everything works as expected except that the poles of the sphere are distorted. It looks like as if the vertices on the poles are disconnected.
Frontview: looks as expected
Topview: looks ugly ;-)
At first, I thought this has something to do with my displacement map and the fact, that I am applying it on a spherical surface, but if I apply it on a cube there are also gaps between the faces.
I'm not sure, what I could do to close those gaps. In a later step, the displacement map should be generically generated by rendering to a texture and using random seeds for the noise, therefore I can't use external programs like Blender or Photoshop to modify the displacement map. Have I done something wrong in the shader, or is this a "normal" behaviour? Can I do anything to avoid that? I read about cubemaps. Could this probably be a solution? And if so, is there a working example for Three.js r57 or higher out there?
Here is my Shadercode:
vertexShader: [
'uniform sampler2D displacementMap;',
'varying vec3 vColor;',
'void main() {',
'vec4 newVertexPos;',
'vec4 dv;',
'float df;',
'dv = texture2D( displacementMap, uv.xy );',
'df = 0.30*dv.x + 0.59*dv.y + 0.11*dv.z;',
'//newVertexPos = vec4(normal * df * 1.0, 0.0) + vec4( position, 1.0 );',
'newVertexPos = vec4( normalize( position ) * df * 1.0 ) + vec4( position, 1.0 );',
'vColor = vec3( dv.x, dv.y, dv.z );',
'gl_Position = projectionMatrix * modelViewMatrix * newVertexPos;',
'}'
].join( "\n" ),
fragmentShader: [
'varying vec3 vColor;',
'void main() {',
'gl_FragColor = vec4( vColor.rgb, 1.0 );',
'}'
].join( "\n" )
And here are the uniforms and the sphere code:
asteroidMaterial = new THREE.ShaderMaterial( {
uniforms: {
//"displacementMap": { type: "t", value: rtTexture },
"displacementMap": { type: "t", value: THREE.ImageUtils.loadTexture( 'txt/asteroid1.png' ) },
},
vertexShader: asteroidShader.vertexShader,
fragmentShader: asteroidShader.fragmentShader,
blending: THREE.NormalBlending,
depthWrite: false,
depthTest: true,
transparent: true,
overdraw: true,
//wrapS: THREE.RepeatWrapping,
//wrapT: THREE.RepeatWrapping,
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
} );
var asteroidGeometry = new THREE.IcosahedronGeometry( 100, 4 );
asteroidGeometry.dynamic = true;
var asteroid = new THREE.Mesh( asteroidGeometry, asteroidMaterial );
asteroid.position = new THREE.Vector3( 0, 0, 200 );
asteroid.visible = true;
scene.add( asteroid );
I just saw, that the code uses a icosahedron instead of a sphere, but the same thing is happening with spheres too.