【问题标题】:Repeated textures are severely distorted/shaking when rotating camera旋转相机时重复的纹理严重扭曲/抖动
【发布时间】:2012-01-09 11:10:48
【问题描述】:

我最初在gamedev 上问过这个问题,但没有一个答案有助于解决问题,我仍然不知道真正的原因是什么。我没有看到任何关于在常见问题解答中跨 SE 重新发布问题的信息,所以我只能希望这没问题。此外,回想起来,这个问题可能更多地与一般的图形编程有关,而不仅仅是游戏开发。

编辑 1 开始

原帖的行为仅适用于 Windows XP 和 Windows 7、浏览器 Firefox 和 Chrome。在 Ubuntu 上,没有这种失真,而是在旋转相机时纹理“抖动”。当旋转停止时,震动停止,但纹理可能不在完全正确的位置。

编辑 1 结束

编辑 3 开始

该程序已在 4 台不同的计算机上进行了测试,但在任何一台计算机上都没有按预期运行。

编辑 3 个末端

我在 WebGL 中有一个大体素,我想用平铺纹理覆盖它,每个平铺在顶点空间中的边长为 1。在这个测试场景中,相机指向负 z 方向,体素的边在 x-y、x-z、y-z 平面内。

较小的体素(即更少的重复)效果很好,但在每个面大约有 2000 个 x 和 y 重复(即体素大小为 2000*2000*2000)时,纹理开始看起来非常难看。当相机垂直指向面部时,无论重复的大小/数量如何,纹理看起来都是正确的,但是对于上述大小的体素,即使几度的任何旋转都会导致可见的问题。增加体素大小会增加失真。反之亦然:对于小体素,无论相机旋转如何,纹理看起来都是正确的。在我看来,尺寸没有硬性阈值,但是当体素的尺寸从每侧大约 2000 增加时,效果开始从零开始逐渐增加。

请参阅http://imgur.com/a/spQIv 以获得可视化效果。第一个图像是它应该看起来的样子,但是当相机旋转时,线条开始像第二个图像一样扭曲。通过增加体素大小和更多地旋转相机,效果会变得更糟。 http://imgur.com/a/wRndy 包含另外两张效果更严重的图片。

纹理(每个纹理一个 X)最初为 512*512 像素。屏幕截图没有以任何方式缩放。

我的第一个猜测是浮点数不准确,但这很难相信,因为对象只有 1000 左右的尺寸。

我的第二个猜测是某种奇怪的 int/float 舍入错误,但由于所有内容始终以浮点数处理,我不知道这是怎么发生的。

我能想到的第三种可能性是,这是不可能的,纹理不应该重复那么多次。然而,这似乎不太可能在国际海事组织。我的猜测(和希望)是存在某种非常基本的问题。

任何关于什么可能导致或通常会导致这种事情的建议都非常感谢,因为我似乎很难自己尝试缩小这个问题的根源。

我正在使用:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.generateMipmap(gl.TEXTURE_2D);

在着色器中:

#ifdef GL_ES
precision highp float;
#endif

我还进行了一些非常基本的计算:对于 32 位浮点数,最大有效位数约为 840 万。对于体素边长 2000(我注意到这是效果变得可见的水平),人们可以天真地期望坐标中的浮点舍入误差约为 0.00025。假设每次重复在屏幕上占用大约 100 个像素,则误差应该明显小于 1 个像素,但事实并非如此。除非我上面的计算不正确,否则我会提名 Float32 不是罪魁祸首,原因一定是其他地方。

线条纹理仅用于可视化问题。其他(更自然的)纹理也存在此问题。

编辑 2 开始

启用或禁用抗锯齿没有明显区别

编辑 2 个末端

【问题讨论】:

  • 你在不同的电脑/浏览器上试过了吗?还是“webgl.prefer-native-gl”设置?
  • 好点,我差点忘了这样做。我已经在最新的 Firefox 和 Chrome 上的 Win XP 以及 Chrome 上的 Ubuntu 上对其进行了测试。无论浏览器如何,Windows 上的行为都大致相同。在 Ubuntu 上,旋转相机时纹理会抖动,但不会扭曲。我将使用此更新编辑问题。你说的设置我没试过,等我到Win XP电脑上再试试。
  • 该选项设置为 true 导致页面根本无法工作:(
  • 您的所有测试是否都在同一台计算机上完成?也许如果您创建一个公共页面,我们可以帮助您在其他硬件上进行测试。
  • 我不想把它扔掉,但是看到你说它在除了一个操作系统之外的任何地方都可以工作,我怀疑可能有一些有问题的驱动程序在起作用。并不是说您无法通过摆弄选项来解决它(您可能遇到了一些晦涩且很少经过测试的边缘案例状态),但我不知道获得您所看到的行为的任何正当理由。

标签: javascript opengl-es rotation textures webgl


【解决方案1】:

我相信您所看到的可能真的是由精度造成的。您正确计算出浮点坐标应该足够漂亮,问题是硬件使用浮点数来查找纹理。纹理插值器单元确实具有相当低的精度(不知道现在如何,但它曾经在旧 GeForce 卡上低至 16 位)。

那么...如何才能超过插值器精度?通过在大型几何体上使用大型纹理坐标(许多重复),这正是您正在做的。补救?细分您的几何图形以使用更小的纹理坐标(您可以以整数步长移动纹理坐标,使它们更接近 0)。

这是一个screenshot,它看起来有多极端(我无法在我的 GeForce 260 上重现该错误,但它在我的 Tegra 2 平板电脑上清晰可见,如下图所示)。

【讨论】:

  • 越想越觉得这是对的。尤其是当您开始提到您正在对某些几何图形进行 50-100K 重复时。如果您的纹理是 512x512,那么您需要 ~0.0019 的精度才能准确地采样每个像素。如果您的卡强制您使用 16 位,那么任何超过 1024 的值都只会产生 0.5(!)的精度,即使使用完整的 32 位浮点数,精度也会在 0-1 范围之外迅速下降。这很容易以您显示的方式混淆您的输出。
  • 这对我来说似乎也很合理的解释。请原谅我的菜鸟,但“细分你的几何图形以使用更小的纹理坐标”是什么意思?将大体素分割成更小的体素?此外,使用更大或更小的纹理尺寸会有帮助吗?
  • 我认为您正在使用三角形或四边形渲染体素。问题是,一旦两个顶点之间的纹理坐标差异太大,或者任何纹理坐标的绝对值太高,在调用任何纹理采样函数之前,正确的值甚至都无法进入片段着色器.所以想法是使用更小的多边形,这样你可以使纹理坐标的差异更小。此外,如果您正在重复纹理,您可以将 texcoords 移近零以使绝对值更小。
  • 这意味着例如,如果我有纹理坐标为 (10, 20, 30) 的三角形(为简单起见只有 1D),我可以将它们移动到 (-10, 0, 10) 并且什么都不会 (视觉上)由于纹理包裹而发生变化。但移位必须是整数步。
  • 更直接地回答您的问题:是的,这意味着较小的问题。在某些情况下,使用较小的纹理会有所帮助,但并非完全如此。这取决于光栅化器是否能够对 texcoords 进行插值(因为错误源于采样期间,并且可以使用较小的纹理来解决 - 但我想这不是你的情况)。
【解决方案2】:

我在 iOS 下遇到了类似的问题。重复纹理 127 次后,坏事开始发生。

有效的解决方案是这样的:

我将GL_TRIANGLE_STRIP 与一些退化的三角形一起使用。纹理与顶点对齐,因此在纹理的边缘有一个不可见(退化)三角形,当我将纹理坐标设置为原点时,纹理被“显示”为镜像。因此,下一个可见三角形显示坐标(0.0, 0.0) 的纹理,并且它永远不会超过坐标(x, 127.0)

有一个blog post 用一些示例和图片对此进行了解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多