copyTextureToTexture导致three.js中出现可怕的锯齿现象 [英] copyTextureToTexture results in horrible aliasing artifacts in three.js
问题描述
当我使用copyTextureToTexture将带有加载图像的texture1复制到texture2时 - 使用相同尺寸和格式创建的数据纹理时,我会得到强大的锯齿效果,因为所有GPU过滤都被禁用 - 至少是它的大部分,因为各向异性似乎有效部分。我在过去的2-3天里一直在努力寻找解决方案,但我仍然不确定这是否是一个three.js错误,或者我错过了什么。任何帮助将不胜感激。
即使是WEBGL解决方案也是受欢迎的,只要它可以和three.js一起工作。
When I use copyTextureToTexture to copy texture1 with a loaded image to texture2 -a datatexture created with the same dimensions and format, I get strong aliasing artifacts like all GPU filtering is disabled -most of it at least, as anisotropy seems to work partially. I'm struggling for the last 2-3 days to find a solution, but still I'm not sure if this is a three.js bug, or am I missing something. Any help will be appreciated. Even a WEBGL solution is welcome, as long as it can work along with three.js.
以下是完整的测试代码:点击在窗口中,您可以在原始纹理和复制纹理之间切换,以比较工件。
The following is the full test-code: by clicking on the window you can toggle between the original and the copied texture to compare the artifacts.
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>
推荐答案
硬件反骚扰仅适用于Framebuffer。这是WebGL的一个已知限制。您可以使用antialasing postProcessing来补偿它和/或渲染到更高的res中间缓冲区,然后在完成渲染纹理后对它们进行下采样以显示分辨率。
Hardware antialasing is only applied to the Framebuffer. It's a known limitation of WebGL. You can use antialasing postProcessing to compensate for it and/or or render to higher res intermediate buffers and then downsample them to display resolution after you're done doing your render to texture.
(编辑:请仔细阅读更多相关信息,我不确定当前的确切限制,因此可能需要进行一些研究)
( Just read more about this and I'm not sure the current exact limitations, so it may need some researching )
这篇关于copyTextureToTexture导致three.js中出现可怕的锯齿现象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!