在OpenGL中扭曲纹理

时间:2011-11-04 08:44:13

标签: math opengl transformation vertex-shader

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

original image

顶点位置为:

(-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)

产生的输出如下:

warped image

下次作为输入时,我使用我刚刚保存的扭曲图像。我想要做的是通过修改顶点坐标来反转我之前做过的扭曲效果。最初我认为取消图像的坐标必须是那种类型的东西:

x_unwarp = 2 * x_original - x_warped

但它不起作用。翘曲效应不会被破坏。我得到的是:

attempted unwarp

知道我做错了什么,应该如何修改顶点坐标或者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)

似乎更直,但仍然不正确:

second attempt to unwarp

第二次更新

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

更新:UV扭曲

这次使用UV变形来完成它。

使用这些UV变形:

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

这产生了:

uv warped

然后尝试使用反转来取消扭曲:

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

看起来像:

unsuccessful uv unwarp

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

完全无能为力。

2 个答案:

答案 0 :(得分:2)

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

如果您这样想的话,现在反转纹理变形是很简单的:第一步的失真协调成为第二步的UV坐标。当然,这需要理解在一定范围内的失真顶点位置。回想一下OpenGL转换管道:

模型视图→投影→剪切→标准化设备坐标。屏幕空间是最后一步,应用了视口尺寸。 NDC坐标在[-1,1]范围内,但是到[0,1]范围很容易:(x + 1)/ 2

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

答案 1 :(得分:1)

如果我正确地理解你的问题(这是不确定的,因为我的答案感觉太简单了:p),为什么不通过应用纹理矩阵简单地修改你的纹理(即用转换来转换UVs,根据需要旋转,剪切等矩阵)而不是移动应用于它的四边形?

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