1

假设我有一个纹理映射到网格屏幕对齐的网格。它看起来像:

原始图像

顶点位置为:

(-1, -1), (1, -1), (-1, 1), (1, 1)

紫外线:

(0, 0), (1, 0), (0, 1), (1,1)

我通过在顶点周围移动来扭曲图像并通过执行glReadPixels().

新的扭曲顶点位置是:

(-1, -1), (0.8, -0.8), (-0.6, 0.6), (0.4, 0.4)

产生的输出如下:

扭曲的图像

下次我使用刚刚保存的扭曲图像作为输入。我要做的是通过修改顶点坐标来反转我之前所做的翘曲效果。最初我认为解开图像的坐标必须是这样的:

x_unwarp = 2 * x_original - x_warped

但它不起作用。翘曲效果不会被撤销。我得到的是这样的:

尝试展开

知道我做错了什么,应该如何修改顶点坐标或 uvs?我确定我的数学错了。

谢谢!

更新

看来我的公式是错误的。我应该使用矩阵:

transform_matrix * x_original = x_warped

进而:

x_unwarped = inverse(tranform_matrix) * x_original

由于我正在做的转换是纯缩放,所以转换矩阵就像:

/     \
| S  0 |
| 0  S |
\      /

其中 S 是比例因子。因此,逆将是:

/         \
| 1/S  0  |
| 0   1/S |
\         /

因此,这将使展开的顶点位置为:

(-1, -1), (1.25, -1.25), (-1.67, 1.67), (2.5, 2.5)

看起来更直,但仍然不正确:

第二次尝试解开

第二次更新

我似乎从一开始就错了。所有渲染中都有一些随机因素。我要解决这个问题,然后再试一次。

更新:UV 扭曲

这次使用 UV 翘曲完成。

使用这些 UV 扭曲:

(0.0, 0.0), (0.9, 0.0), (0.0, 0.8), (0.7, 0.7)

这产生了:

紫外线翘曲

然后尝试使用倒数展开:

(0.0, 0.0), (1/0.9, 0.0), (0.0, 1/0.8), (1/0.7, 1/0.7)

看起来像:

不成功的 uv unwarp

这也没有做到。我开始担心我忽略的 1/0 案例。

完全无知。

4

2 回答 2

2

您遇到的一件事是透视不正确的纹理映射(您可以在第一张图片中看到,对于构成四边形的两个三角形中的每一个,纹理坐标的插值都不同)。您可以在一个大的单个四边形上使用透视校正(使用片段着色器并在那里实现算法),或者将您的四边形细分为更小的补丁。

现在反转纹理扭曲很简单,如果你这样想的话:第一步的扭曲坐标变成了第二步的 UV 坐标。当然这需要了解一定范围内的畸变顶点位置。回想一下 OpenGL 转换管道:

Modelview → Projection → Clipping → Normalized Device Coordinates。屏幕空间是最后一步,应用了视口尺寸。NDC 坐标在 [-1,1] 范围内,但到达 [0,1] 范围很容易:(x+1)/2

所以你要做的是执行转换管道(你可以省略剪裁,但你必须应用透视分割),这为你提供了去失真的 UV 坐标。

于 2011-11-04T10:27:58.767 回答
1

如果我正确理解了您的问题(不确定,因为我的回答感觉太简单了:p),为什么不简单地通过应用纹理矩阵来修改您的纹理(即通过平移、旋转、剪切来变换 UV等矩阵)而不是移动它应用到的四边形?

这将使反转转换成为反转原始转换矩阵的简单问题。

于 2011-11-04T09:01:20.823 回答