我想在一个已经通过非仿射变换(更具体地说是透视变换)变换的矩形上放置纹理 .
我有一个非常复杂的实现基于openscenegraph并加载我自己的顶点和片段着色器 . 问题始于着色器很久以前写的并使用GLSL 120 .
OpenGL端用C语言编写,最简单的形式是加载纹理并将其应用于四边形 . 直到最近,一切都运行正常,因为四边形最多是仿射变换(旋转平移),所以纹理的渲染是正确的 .
现在我们想支持任何形状的四边形,包括这样的东西:http://ibin.co/1dbsGPpzbkOX
正如您在上图中所看到的,中间的纹理在中间是不正确的(箭头所示)经过数小时的研究后我发现这是由于OpenGL将四边形分成三角形并独立渲染每个三角形 . 如果我的四边形如图所示,这当然是不正确的,因为第四点会影响纹理拉伸 . 然后我甚至发现这个问题有一个名称:它是“透视不正确的纹理坐标插值”,如下所述:[1]
寻找解决方案,我遇到了这篇文章,其中提到了在以后的GLSL版本中使用“smooth”属性:[2]但这意味着将我的着色器更新为更新的版本 .
我发现的一个替代方法是使用GL_Hints,如下所述:[3]但这里的缺点是它只是一个提示,并且没有办法确保它被使用 .
现在我已经展示了我的研究,这是我的问题:
更新我的(复杂)着色器和所有与它一起使用的OpenGL以遵守新的OpenGL管道范例将非常耗时,因此我尝试使用GLSL“版本330兼容性”并将“变化”更改为“平滑”和“平滑”,以及在C方面添加GL_NICE提示,但这些更改并没有解决我的问题 . 这是正常的,因为兼容模式不知何故不支持这种正确的透视变换?或者还有什么我需要做的事情?或者,有没有更好的方法来获得此功能而无需重构所有内容?
这是我的顶点着色器:
#version 330 compatibility
smooth out vec4 texel;
void main(void) {
gl_Position = ftransform();
texel = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}
并且片段着色器太复杂了,但它始于
#version 330 compatibility
smooth in vec4 texel;
1 回答
使用derhass的提示我以一种截然不同的方式解决了问题 .
确实,“平滑”关键字不是问题,而是投影纹理映射 .
为了解决这个问题,我直接从我的C代码传递到frag着色器透视变换矩阵,并在那里自己计算了“正确”的纹理坐标,而没有使用GLSL的重心插值 .
为了帮助任何有同样问题的人,这里是我的着色器的简化版本:
.vert
.frag
请注意,上面的片段着色器代码没有完全像那样测试,所以我不能保证它可以开箱即用,但它应该主要在那里 .