【问题标题】:copyTextureToTexture results in horrible aliasing artifacts in three.jscopyTextureToTexture 在 three.js 中导致可怕的锯齿伪影
【发布时间】:2018-12-06 20:34:57
【问题描述】:

当我使用 copyTextureToTexture 将带有已加载图像的纹理 1 复制到纹理 2(使用相同尺寸和格式创建的数据纹理)时,我会得到强烈的锯齿伪影,例如所有 GPU 过滤都已禁用 - 至少其中大部分都已禁用,因为各向异性似乎有效部分。在过去的 2-3 天里,我一直在努力寻找解决方案,但我仍然不确定这是一个 three.js 错误,还是我遗漏了什么。任何帮助将不胜感激。 即使是 WEBGL 解决方案也是受欢迎的,只要它可以与 three.js 一起工作。

以下是完整的测试代码:通过单击窗口,您可以在原始纹理和复制纹理之间切换以比较工件。

var w = window.innerWidth;
var h = window.innerHeight;
var hx = w / 2;
var hy = h / 2;

var camera, scene, renderer, tog1;
var mouseX = 0,
  mouseY = 0;

var container = document.createElement('div');
document.body.appendChild(container);

camera = new THREE.PerspectiveCamera(35, w / h, 10, 25000);
camera.position.z = 20;

scene = new THREE.Scene();
scene.background = new THREE.Color("#f2f7ff");
scene.add(new THREE.AmbientLight("#eef0ff"));

var light = new THREE.DirectionalLight("#ffffff", 2);
light.position.set(1, 1, 1);
scene.add(light);

const myurl = "https://i.imgur.com/UiTMJzv.png";
const textureLoader = new THREE.TextureLoader();
const texture1 = textureLoader.load(myurl, setup);

function onDocumentMouseMove(event) {
  container.focus();
  mouseX = (event.clientX - hx);
  mouseY = (event.clientY - hy);
}

function setup() {

  renderer = new THREE.WebGLRenderer({
    antialias: false
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(w, h);
  renderer.domElement.style.position = "relative";
  container.appendChild(renderer.domElement);

  var anisomax = renderer.capabilities.getMaxAnisotropy();
  texture1.anisotropy = anisomax;
  texture1.needsUpdate = true;

  //create datatexture
  var data = new Uint8Array(1024 * 1024 * 3);
  var texture2 = new THREE.DataTexture(data, 1024, 1024, THREE.RGBFormat);
  //texture2.minFilter = THREE.LinearMipMapLinearFilter; //THREE.NearestMipMapLinearFilter;//THREE.NearestFilter;//THREE.NearestMipMapNearestFilter; //THREE.LinearFilter;
  //texture2.magFilter = THREE.LinearFilter;	
  //texture2.generateMipmaps = true;	
  texture2.anisotropy = anisomax;
  texture2.needsUpdate = true;

  material = new THREE.MeshPhongMaterial({
    color: "#ffffff",
    map: texture2
  });
  material.side = THREE.DoubleSide;
  var geometry = new THREE.PlaneBufferGeometry(400, 400);
  var mesh = new THREE.Mesh(geometry, material);
  mesh.rotation.x = Math.PI / 2;
  scene.add(mesh);

  //copy loaded texture to datatexture
  renderer.copyTextureToTexture(new THREE.Vector2(0, 0), texture1, texture2);

  document.addEventListener('mousemove', onDocumentMouseMove, false);

  var inf = document.getElementById("info");
  inf.innerHTML = "Copied Texture to DataTexture</br>--click to toggle--";

  // toggle between texture loaded and coppied
  document.addEventListener('mousedown', () => {

    tog1 = (tog1 === false) ? true : false;

    scene.remove(mesh);
    if (tog1 === true) {
      material = new THREE.MeshPhongMaterial({
        color: "#ffffff",
        map: texture2
      });
      material.side = THREE.DoubleSide;
      mesh = new THREE.Mesh(geometry, material);
      mesh.rotation.x = Math.PI / 2;
      inf.innerHTML = "Copied Texture to DataTexture</br>--click to toggle--";
    } else {
      material = new THREE.MeshPhongMaterial({
        color: "#ffffff",
        map: texture1
      });
      mesh = new THREE.Mesh(geometry, material);
      mesh.rotation.x = -Math.PI / 2;
      inf.innerHTML = "Original Texture</br>--click to toggle--";
    }
    scene.add(mesh);
  });

  animate();
} //end setup

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  camera.position.x += (mouseX - camera.position.x);
  camera.position.y = 1000;
  camera.lookAt(scene.position);

  renderer.clear();
  renderer.render(scene, camera);
}
body {
  color: #000;
  font-family: Monospace;
  font-size: 13px;
  text-align: center;
  background-color: #fff;
  margin: 0px;
  padding: 0px;
  overflow: hidden;
}

#info {
  position: absolute;
  font-weight: bold;
  top: 0px;
  width: 100%;
  padding: 5px;
  z-index: 100;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <title>copyTextureToTexture test</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  <style>

  </style>
</head>

<body>
  <div id="info"></div>
</body>

</html>

【问题讨论】:

  • 不相关,但是 setTimeout 试图解决的问题是什么?
  • 在某些时候没有它就无法工作,但在以后的形式中它不需要它,你是对的。感谢您使 sn-p 工作 - 秘诀是什么?
  • 我将您的图像复制到常规 imgur 以使其正常工作。见meta.stackoverflow.com/a/370236/128511
  • @user5515 你有没有找到解决办法?

标签: javascript three.js textures


【解决方案1】:

硬件抗锯齿仅适用于帧缓冲区。这是 WebGL 的一个已知限制。您可以使用抗锯齿后期处理来补偿它和/或渲染到更高分辨率的中间缓冲区,然后在完成对纹理的渲染后对它们进行下采样以显示分辨率。

(编辑:请阅读更多关于此的内容,我不确定当前的确切限制,因此可能需要进行一些研究)

【讨论】:

  • 谢谢,但我正在复制到另一个纹理,以便将其用作任何其他普通纹理,例如加载到帧缓冲区,我不是在谈论我们放置的“antialias: true” webglrenderer - 我什至将它设置为 false,因为第一个纹理不需要它。不起作用的是 minFilter 和 magFilter。如果我取消注释这些行并将 mipmaping 设置为 true,则渲染器会淡化图像而不是切换到另一个自动生成的 mipmap。各向异性的作用也小得多。这只是字节复制,我不敢相信这会造成这么多麻烦......
  • “例如加载到帧缓冲区”,废弃这个,我的意思是像任何其他纹理一样使用,在增加角度时线性模糊 - 这是行不通的。
  • 你的纹理是 2 的幂吗?
  • 是的,1024x1024。我已经尝试了其他几种二维的幂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 2021-10-05
  • 1970-01-01
  • 2013-06-17
相关资源
最近更新 更多