【问题标题】:Perspective-correct shader rendering透视正确的着色器渲染
【发布时间】:2014-10-23 17:50:29
【问题描述】:

我想在一个已通过非仿射变换(更具体地说是透视变换)变换的矩形上放置纹理。

我有一个基于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;

【问题讨论】:

标签: opengl glsl compatibility


【解决方案1】:

使用 derhass 的提示,我以完全不同的方式解决了问题。

确实,“smooth”关键字不是问题,而是投影纹理映射。

为了解决这个问题,我直接从我的 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;
}

请注意,上面的片段着色器代码没有经过完全一样的测试,所以我不能保证它可以开箱即用,但它应该大部分都在那里。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-29
    • 2019-06-06
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多