Desperate to remove this UV seam introduced by custom shader code

I’d be really grateful if someone can help me get out of this, I’ve been stuck for 2 days! Live code at mystifying-mclean-y7dymx - CodeSandbox . In the codesandbox demo, once it’s loaded, drag the earth slightly to the right and you should see the thin seam.

I’ve been simulating Earth, with clouds and cloud shadows. For the earth’s texture and the cloud’s texture, I applied them to MeshStandardMaterial with SphereGeometry respectively (2 meshes). As for cloud shadows, I’ve been trying to create a “negative clouds map” directly in the earth’s fragment shader via onBeforeCompile. The effect can be achieved but there’s a thin seam where the earth’s UV texture joins at its sides(x=0 and x=1). So for debugging purposes, I simplified the original code to display cloudsMapValue as earth’s diffuse color so I can see the seam clearer:

shader.fragmentShader = shader.fragmentShader.replace(
    "#include <emissivemap_fragment>",
    `
    #include <emissivemap_fragment>

    // Since I made the clouds spin twice as fast as the earth,
    // in order to get the shadows(clouds) position in this earth's fragment shader
    // we need to minus uv_xOffset
    float xTex = fract(1.0 + (vMapUv.x - fract(uv_xOffset)));
    float cloudsMapValue = texture2D(tClouds, vec2(xTex, vMapUv.y)).r;
    diffuseColor.rgb = vec3(cloudsMapValue);
`
);

Try with these two changes:

  • adding wrapping mode
    shader.uniforms.tClouds.value.wrapS = THREE.RepeatWrapping;

  • simplifying texture offset calculation
    float xTex = vMapUv.x - uv_xOffset;

earthMat.onBeforeCompile = function (shader) {
      shader.uniforms.tClouds = { value: cloudsMap };
      shader.uniforms.uv_xOffset = { value: 0 };
      shader.uniforms.tClouds.value.wrapS = THREE.RepeatWrapping; // <-- ADDED LINE
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <common>",
        `
        #include <common>
        uniform sampler2D tClouds;
        uniform float uv_xOffset;
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <emissivemap_fragment>",
        `
        #include <emissivemap_fragment>

        float xTex = vMapUv.x - uv_xOffset; // <-- CHANGED LINE
        float cloudsMapValue = texture2D(tClouds, vec2(xTex, vMapUv.y)).r;
        diffuseColor.rgb = vec3(cloudsMapValue);
      `
      );

      earthMat.userData.shader = shader;
    };
3 Likes

Haha you beat me to it.

1 Like

OMG, thanks my savior!