3d 纹理坐标的透视校正
我正在编写一个软件渲染器,目前运行良好,但我试图对纹理坐标进行透视校正,但这似乎不正确。我的渲染器使用与 opengl 相同的矩阵数学。要栅格化三角形,我执行以下操作:
使用模型视图和投影矩阵转换顶点,然后转换为剪辑坐标。
对于每个三角形中的每个像素,计算重心坐标以插值属性(颜色、纹理坐标、法线等)
为了纠正透视,我使用透视校正插值: (w 是顶点的深度坐标,c 是顶点的纹理坐标,b 是顶点的重心权重)
<前><代码>1/w = b0*(1/w0) + b1*(1/w1) + b2*(1/w2) c/w = b0*(c0/w0) + b1*(c1/w1) + b2*(c2/w2) c = (c/w)/(1/w)
这应该可以纠正透视,并且有一点帮助,但是仍然存在明显的透视问题。我在这里遗漏了一些东西,也许是一些舍入问题(我在所有数学中都使用浮点数)?
在此图像中,纹理坐标中的误差沿对角线明显可见,这是除以深度坐标的结果。
另外,这通常是针对纹理坐标完成的...对于其他属性(例如法线)是否有必要等)还有吗?
I'm writing a software renderer which is currently working well, but I'm trying to get perspective correction of texture coordinates and that doesn't seem to be correct. I am using all the same matrix math as opengl for my renderer. To rasterise a triangle I do the following:
transform the vertices using the modelview and projection matrixes, and transform into clip coordinates.
for each pixel in each triangle, calculate barycentric coordinates to interpolate properties (color, texture coordinates, normals etc.)
to correct for perspective I use perspective correct interpolation:
(w is depth coordinate of vertex, c is texture coordinate of vertex, b is the barycentric weight of a vertex)
1/w = b0*(1/w0) + b1*(1/w1) + b2*(1/w2) c/w = b0*(c0/w0) + b1*(c1/w1) + b2*(c2/w2) c = (c/w)/(1/w)
This should correct for perspective, and it helps a little, but there is still an obvious perspective problem. Am I missing something here, perhaps some rounding issues (I'm using floats for all math)?
See in this image the error in the texture coordinates evident along the diagonal, this is the result having done the division by depth coordinates.
Also, this is usually done for texture coordinates... is it necessary for other properties (e.g. normals etc.) as well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我最近破解了这个问题的代码。如果您打算在将纹理分配给曲面之前修改内存中的纹理,则可以使用单应性。这在计算上是昂贵的,并且给你的程序增加了额外的依赖。有一个很好的技巧可以为您解决这个问题。
OpenGL 自动对正在渲染的纹理应用透视校正。您需要做的就是将纹理坐标 (UV - 0.0f-1.0f) 乘以平面每个角的 Z 分量(XYZ 位置向量的世界空间深度),它将“摆脱”OpenGL 的透视校正。
我最近询问并解决了这个问题。尝试一下此链接:
纹理映射梯形OpenGL 中的方形纹理
我读到的解决此问题的论文名为 "使用图像空间简化和 Mor 导航静态环境phing” - 第 9 页附录 A .
希望这有帮助!
CT
I cracked the code on this issue recently. You can use a homography if you plan on modifying the texture in memory prior to assigning it to the surface. That's computationally expensive and adds an additional dependency to your program. There's a nice hack that'll fix the problem for you.
OpenGL automatically applies perspective correction to the texture you are rendering. All you need to do is multiply your texture coordinates (UV - 0.0f-1.0f) by the Z component (world space depth of an XYZ position vector) of each corner of the plane and it'll "throw off" OpenGL's perspective correction.
I asked and solved this problem recently. Give this link a shot:
texture mapping a trapezoid with a square texture in OpenGL
The paper I read that fixed this issue is called, "Navigating Static Environments Using Image-Space Simplification and Morphing" - page 9 appendix A.
Hope this helps!
ct
从 UV 坐标到 3D 平面的唯一正确变换是单应变换。
http://en.wikipedia.org/wiki/Homography
您必须在某个时刻拥有它你的计算。
要自己找到它,您可以编写纹理的任何像素的投影(与顶点相同)并将它们反转以从屏幕坐标获取纹理坐标。
它将以单应变换的形式出现。
The only correct transformation from UV coordinates to a 3D plane is an homographic transformation.
http://en.wikipedia.org/wiki/Homography
You must have it at some point in your computations.
To find it yourself, you can write the projection of any pixel of the texture (the same as for the vertex) and invert them to get texture coordinates from screen coordinates.
It will come in the form of an homographic transform.
是的,这看起来就像传统的破碎透视凹痕。不过你的算法看起来是正确的,所以我真的不确定可能出了什么问题。我会在稍后渲染时检查您是否确实使用了新计算的值?这看起来确实像是您费尽心思计算透视正确值,然后使用基本的未校正值进行渲染。
Yeah, that looks like your traditional broken-perspective dent. Your algorithm looks right though, so I'm really not sure what could be wrong. I would check that you're actually using the newly calculated value later on when you render it? This really looks like you went to the trouble of calculating the perspective-correct value, and then used the basic non-corrected value for rendering.
您需要通知 OpenGL 您需要对像素进行透视校正
您所观察到的是线性纹理映射的典型失真。在无法进行逐像素透视校正的硬件(例如 PS1)上,标准解决方案只是细分为较小的多边形,以使缺陷不那么明显。
You need to inform OpenGL that you need perspective correction on pixels with
What you are observing is the typical distortion of linear texture mapping. On hardware that is not capable of per-pixel perspective correction (like for example the PS1) the standard solution is just subdividing in smaller polygons to make the defect less noticeable.