Three.js Y Axis Offset for Equirectangular Image Not Working

103 views Asked by At

I have a mash with two textures that I mix. Each texture is a panoramic equirectangular image. I need to offset only one of two textures by providing degrees for X or Y axis.

// usage: applyOffset(90, 90);
const applyOffset = (xAngle, yAngle) => {
  const offsetXradians = xAngle * (Math.PI / 180.0);
  const offsetYradians = yAngle * (Math.PI / 180.0);
  uniforms['offset0'].value.set(offsetXradians, offsetYradians, 0);
};
// definition: uniforms['offset0'] = { type: "v3", value: new THREE.Vector3(0, 0, 0) }

I achieved X axis rotation to offset left or right. But Y axis is not going up or down - it spins clockwise instead. I tried to adjust the XYZ order but unsuccessfully.

mat3 rotationMatrix3(vec3 angles) {
    mat3 rotationX = mat3(1, 0, 0, 0, cos(angles.x), sin(angles.x), 0, -sin(angles.x), cos(angles.x));
    mat3 rotationY = mat3(cos(angles.y), 0, -sin(angles.y), 0, 1, 0, sin(angles.y), 0, cos(angles.y));
    mat3 rotationZ = mat3(cos(angles.z), sin(angles.z), 0, -sin(angles.z), cos(angles.z), 0, 0, 0, 1);
    return rotationX * rotationY * rotationZ;
}

Here is the fragment shader:

  void main() {
    vec3 vWorldPositionScaled0 = mix(vWorldPosition, tCubePosition0, scale0);
    vWorldPositionScaled0.x *= -1.0;

    vec3 vWorldPositionScaled1 = mix(vWorldPosition, tCubePosition1, scale1);
    vWorldPositionScaled1.x *= -1.0;

    vec4 tex0, tex1;
    
    mat3 rotationMatrix0 = rotationMatrix3(offset0);
    vWorldPositionScaled0 = rotationMatrix0 * vWorldPositionScaled0;
    mat3 rotationMatrix1 = rotationMatrix3(offset1);
    vWorldPositionScaled1 = rotationMatrix1 * vWorldPositionScaled1;
    
    tex0 = textureCube(tCube0, vec3( tFlip * vWorldPositionScaled0.x, vWorldPositionScaled0.yz ));
    tex1 = textureCube(tCube1, vec3( tFlip * vWorldPositionScaled1.x, vWorldPositionScaled1.yz ));

    gl_FragColor = mix(tex1, tex0, mixAlpha);
  }

How do I get Y-axis offset correctly work offsetting up and down?Here is a JSFiddle with entire code sample: https://jsfiddle.net/b2yjsp8h/

1

There are 1 answers

1
Łukasz D. Mastalerz On

Check this one:

Remove applyOffset(x,x);

And modify update function

const gui = new dat.GUI();
const controls = {
    offsetX: 0,
    offsetY: 0
};
gui.add(controls, 'offsetX', -180, 180).onChange(() => updateCameraAngles());
gui.add(controls, 'offsetY', -180, 180).onChange(() => updateCameraAngles());

const updateCameraAngles = () => {
    const offsetX = THREE.Math.degToRad(controls.offsetY);
    const offsetY = THREE.Math.degToRad(controls.offsetX);
    
    applyOffset(offsetX, offsetY);
};

//---

const update = () => {

    const distX = coords.current.x - coords.delta.x;
    const distY = coords.current.y - coords.delta.y;

    coords.delta.x += distX / 7;
    coords.delta.y += distY / 7;

    coords.phi = THREE.Math.degToRad(90 - coords.delta.x);
    coords.theta = THREE.Math.degToRad(coords.delta.y);

    coords.target.x = 500 * Math.sin(coords.theta) * Math.cos(coords.theta);
    coords.target.y = 500 * Math.cos(coords.phi);
    coords.target.z = 500 * Math.sin(coords.phi) * Math.sin(coords.theta);

    camera.lookAt(coords.target);
    renderer.render(scene, camera);

};