Hi, post this question on StackOverflow with no avail so I thought I’ll to come to the score to ask it.
I’m working on a project where I need to texture a cubed sphere using noise in Three.js, so that the texture is continuous across all six sides. I’ve already created the cube using six planes for each side, but I’m having trouble getting the noise to be continuous across the cubed sphere.
Can anyone provide some guidance on how to texture a cubed sphere using noise in Three.js, so that the texture is continuous across all six sides?
WORKING EXAMPLE:EXAMPLE
Here is the cube with noise:
Here is the cube transformed into a sphere (as you can see the noise isn’t continuous between each side):
Here is an image of what I want the outcome to look like:
this is how the cube this created
var front = buildMesh(texture);
var fg = new THREE.Group(front)
fg.add(front)
var back = buildMesh(texture);
var bg = new THREE.Group(back)
bg.add(back)
bg.position.z = -w;
bg.rotation.y=(Math.PI)
var right = buildMesh(texture);
var rg = new THREE.Group(right)
rg.add(right)
rg.position.z = -((w)/2);
rg.position.x = ((w)/2);
rg.rotation.y = (Math.PI/2)
var left = buildMesh(texture);
var lg = new THREE.Group(left)
lg.add(left)
lg.position.z = -((w)/2);
lg.position.x = -((w)/2);
lg.rotation.y=(-Math.PI/2)
var top = buildMesh(texture);
var tg = new THREE.Group(top)
tg.add(top)
tg.position.z = -((w)/2);
tg.position.y = ((w)/2);
tg.rotation.x=(-Math.PI/2)
var bot = buildMesh(texture);
var bog = new THREE.Group(bot)
bog.add(bot)
bog.position.z = -((w)/2);
bog.position.y = -((w)/2);
bog.rotation.x=(Math.PI/2)
var g = new THREE.Group()
g.add(fg)
g.add(bg)
g.add(lg)
g.add(rg)
g.add(tg)
g.add(bog)
scene.add(g)
function buildMesh(t){
let geometry = new THREE.PlaneGeometry(w, w,50,50);
uniforms = {u_tex: {value: t },wTl:{value:new THREE.Vector3()},ps:{value:new THREE.Vector3()}};
let material = new THREE.ShaderMaterial({
uniforms: uniforms,
fragmentShader: fragmentShader(),
vertexShader: vertexShader(),
wireframe:false
});
var mesh = new THREE.Mesh(geometry, material);
return mesh
}
this is how i’m calculating my ‘localceter’ vertex shader variable to normalize each plane.
var sides = [
...fg.children,
...bg.children,
...rg.children,
...lg.children,
...tg.children,
...bog.children,
]
var cnt = centerPosition(g)
var localCenter = new THREE.Vector3();
for (let index = 0; index < sides.length; index++) {
const element = sides[index];
element.worldToLocal(localCenter.copy(cnt))
element.material.uniforms['wTl'].value = localCenter
}
function centerPosition(g) {
bbox.expandByObject(g);
var center = new THREE.Vector3();
bbox.getCenter(center);
return center
}
the fragment and vertex shader
function vertexShader(){
return `
varying vec2 vUv;
uniform vec3 wTl;
vec3 planeToSphere(vec3 p, vec3 localCenter){
p = p - localCenter;
p=normalize(p);
float length = -length(p);
p = p * length * (localCenter.z*1.0);
p = p+localCenter;
return p;
}
varying vec3 v3n;
void main() {
vUv = uv;
vec3 newPosition = planeToSphere(position,wTl) ;
vec3 worldp = ( modelMatrix * vec4(newPosition,1.0)).xyz;
float n = snoise(worldp*.04);
v3n=vec3(n,n,n);
vec3 finalp = newPosition+normal*n;
gl_Position = projectionMatrix * modelViewMatrix * vec4( finalp, 1.0 ) ;
}
`
}
function fragmentShader(){
return `
varying vec2 vUv;
varying vec3 v3n;
void main() {
gl_FragColor = vec4(v3n,1.0);
}
`
}