我想把一个纹理放在一个矩形上,它已经被一个非仿射变换(更具体地说,是一个透视变换)所转换。
我有一个非常复杂的实现基于开放图形和加载我自己的顶点和片段着色器。这个问题开始于这样一个事实:着色器是很久以前写的,并且正在使用GLSL 120。
OpenGL端是用C++编写的,并以其最简单的形式编写,加载纹理并将其应用于四角体。直到最近,一切都很好,因为四边形最多是仿射变换(旋转+平移),所以纹理的渲染是正确的。
然而,现在我们希望支持任意形状的四角体,包括如下所示:http://ibin.co/1dbsGPpzbkOX
正如您在上面的图片中所看到的,它的纹理在中间是不正确的(用箭头表示),经过几个小时的研究,我发现这是由于OpenGL将四边形分割成三角形,并独立地呈现每个三角形。这当然是不正确的,如果我的四边形是如图所示,因为第四个点影响纹理拉伸。我甚至发现这个问题有一个名称:它是一个“前瞻性的不正确的纹理坐标插值”,如下所述:1
为了寻找这方面的解决方案,我遇到了这篇文章,其中提到在以后的GLSL版本中使用“平滑”属性:2,但这意味着将我的着色器更新到一个更新的版本。
我发现的另一种选择是使用GL_Hints,如这里所描述的:3但这里的缺点是,它只是一个提示,没有办法确保它被使用。
现在我已经展示了我的研究成果,下面是我的问题:
更新我的(复杂的)着色器和所有遵循新的OpenGL管道范型的OpenGL太费时了,所以我尝试使用GLSL“Version330兼容性”,将“可变”更改为“平滑”和“平滑in",并在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;发布于 2014-10-23 09:50:29
利用德哈斯的暗示,我以一种完全不同的方式解决了这个问题。
的确,“平滑”关键字不是问题,而是投影纹理映射。
为了解决这个问题,我从我的C++代码直接传递到框架阴影透视变换矩阵,并计算了“正确的”纹理坐标在那里自己,而不使用GLSL的重心插值。
为了帮助任何有同样问题的人,这里有一个我的着色器的压缩版本:
.vert
#version 330 compatibility
smooth out vec4 inQuadPos; // Used for the frag shader to know where each pixel is to be drawn
void main(void) {
gl_Position = ftransform();
inQuadPos = gl_Vertex;
}.frag
uniform mat3 transformMat; // the transformation between texture coordinates and final quad coordinates (passed in from c++)
uniform sampler2DRect source;
smooth in vec4 inQuadPos;
void main(void)
{
// Calculate correct texel coordinate using the transformation matrix
vec3 real_texel = transformMat * vec3(inQuadPos.x/inQuadPos.w, inQuadPos.y/inQuadPos.w, 1);
vec2 tex = vec2(real_texel.x/real_texel.z, real_texel.y/real_texel.z);
gl_FragColor = texture2DRect(source, tex).rgba;
}请注意,上面的片段着色器代码还没有经过完全那样的测试,所以我不能保证它会开箱即用,但是它应该大部分都在那里。
https://stackoverflow.com/questions/26345156
复制相似问题