Seams on cube edges when using texture atlas with

2020-02-15 04:28发布

问题:

I have seams between horizontal faces of the cube when use texture atlas in three.js.
This is demo: http://jsfiddle.net/rnix/gtxcj3qh/7/ or http://jsfiddle.net/gtxcj3qh/8/ (from comments)

Screenshot of the problem:
Here I use repeat and offset:

    var materials = [];
    var t = [];
    var imgData = document.getElementById("texture_atlas").src;
    for ( var i = 0; i < 6; i ++ ) {
      t[i] = THREE.ImageUtils.loadTexture( imgData ); //2048x256
      t[i].repeat.x  = 1 / 8;
      t[i].offset.x = i / 8;
      //t[i].magFilter = THREE.NearestFilter;
      t[i].minFilter = THREE.NearestFilter;
      t[i].generateMipmaps = false;
      materials.push( new THREE.MeshBasicMaterial( { map: t[i], overdraw: 0.5 } ) );
    }

    var skyBox = new THREE.Mesh( new THREE.CubeGeometry( 1024, 1024, 1024), new THREE.MeshFaceMaterial(materials) );
    skyBox.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, -1 ) );
    scene.add( skyBox );

The atlas has size 2048x256 (power of two). I also tried manual UV-mapping instead of repeat, but the result is the same. I use 8 tiles instead of 6 because I have thought precision of division 1/6 causes the problem, but not.

Pixels on this line are from next tile in atlas. I tried completly white atlas and there was not any artefacts. This explains why there are not seams on vertical borders of Z-faces. I have played with filters, wrapT, wrapS and mipmaps but it does not help. Increasing resolution does not help. There is 8192x1024 atlas http://s.getid.org/jsfiddle/atlas.png I tried another atlas, the result is the same.

I know that I can split atlas into separate files and it works perfectly but it is not convenient.

Whats wrong?

回答1:

I think the issue is the filtering problem with texture sheets. On image borders in a texture sheet, the gpu may pick the texel from either the correct image or the neighbor image due to limited precision. Because the colors are usually very different, this results in the visible seams. In regular textures, this is solved with CLAMP_TO_EDGE.

If you must use texture alias, then you need to fake CLAMP_TO_EDGE behavior by padding the image borders. See this answer https://gamedev.stackexchange.com/questions/61796/sprite-sheet-textures-picking-up-edges-of-adjacent-texture. It should look something like this: (exaggerated borders for clarity)

Otherwise, the simpler solution is to use a different texture for each face. Webgl supports the cube texture and that is usually used the majority of the time to implement skyboxes.