【问题标题】:Outer artifacts when using GL_LINEAR in Texture OpenGL在纹理 OpenGL 中使用 GL_LINEAR 时的外部伪影
【发布时间】:2018-07-03 15:30:47
【问题描述】:

我成功地在 openGL 中使用纹理生成了高度图。该数据的全貌如下图所示。但是,当我在我的 glTexParameteri (MinMag) 中使用 GL_LINEAR 选项时,它给了我外部工件。

这是我的 glTexParameter

if (interpolate) {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

这是我的片段着色器代码

    "varying vec2 tex;\n"
    "uniform int colorSizeI;\n"
    "uniform vec4 colorTable[512];\n"
    "uniform vec2 minmaxZ;\n"
    "uniform vec3 backgroundColor;\n"
    "uniform sampler2D diffuse;\n"
    "uniform float transparency;\n"
    "void main() {\n"
    "   float color = texture2D(diffuse, tex).r;\n"
    "   float h = (color - minmaxZ[0])/(minmaxZ[1] - minmaxZ[0]);\n"
    "   float colorSizeF = float(colorSizeI);\n"
    "   int i = 0;\n"
    "   float j = 0.0f;\n"
    "   vec3 base;\n"
    "   if (color == 0.0f) {\n"
    "       base = vec3(0.0f, 0.0f, 0.0f);}\n"
    "   else if (color <= minmaxZ[0]) {\n"
    "       base = colorTable[0].xyz;}\n"
    "   else if (color >= minmaxZ[1]) {\n"
    "       base = colorTable[colorSizeI - 1].xyz;}\n"
    "   else { \n"
    "       while (h >= (j + 1.0f)/colorSizeF) {\n"
    "           i += 1;\n"
    "           j += 1.0f;}\n"
    "       base = mix(colorTable[i].xyz, colorTable[i+1].xyz, colorSizeF*(h - (j/colorSizeF)));}\n"
    "   gl_FragColor = vec4(base, transparency);\n"
    "}\n";

这是使用 GL_Nearest 时的图像(一切正常)

这是使用 GL_Linear 时的图像(出现外部插值伪影)

那么,有谁知道如何移除这些工件?

注意:当 color = 0 时,外部的黑色也是考虑数据。

【问题讨论】:

  • 夹边GL_CLAMP_TO_EDGEGL_CLAMP
  • 我用了GL_CLAMP_TO_EDGE,忘了说,当z = 0时,正方形外面的黑色实际上也是数据;所以我不相信这是因为texturewrap。
  • 你必须提供所有的::glTexParameteri 调用,这样我们才能看到你在做什么
  • 如果你这样做会发生什么gl_FragColor = texture2D(diffuse, tex)
  • 我使用纹理来避免使用顶点和索引(减少内存)。在纹理(红色)数据中包含将根据片段着色器中的计算以颜色显示的高度图。因此,如果我执行gl_FragColor = texture2D(diffuse, tex),它将不会显示我想要显示的数据。

标签: c++ opengl texture-mapping


【解决方案1】:

我假设您的纹理包装当前是 GL_REPEAT。你应该尝试另一个。

GL_MIRRORED_REPEAT 或 GL_CLAMP_TO_EDGE 应该可以工作。

【讨论】:

  • 我用了GL_CLAMP_TO_EDGE,忘了说,当z = 0时,正方形外面的黑色实际上也是数据;所以我不相信这是因为texturewrap。
  • 好的,那么这行可能是问题所在:base = colorTable[colorSizeI - 1].xyz;} 看起来不对,但无法为您提供更多帮助,因为我不知道统一值。
  • 我在uniform vec4 colorTable[512] 中准备了缓冲区,因为我的 colorTable 有一些选项,并且每个选项都有不同的颜色数量。 colorSizeI - 1 是为了确保如果高度超过某个值,颜色将是 colorTable 中的最后一个有效值。所以我尝试按照您的建议进行更改,但插值伪影仍然存在。
  • 我想现在我明白了你想要做什么:你有一个高度值从 0.0 到 1.0 的纹理,但是这个纹理的边界值为 1.0 = 最大高度。 OpenGL 现在将这些值沿边界的中间插入 1.0。 - 看起来你必须从纹理中移除边框或保留 GL_NEAREST。
【解决方案2】:

错误是因为从“空颜色”插入到 colr 表中的实际颜色。简而言之:你不能那样做。这个概念被打破了。回到绘图板。

最简单的解决方案是没有空颜色,将四边形限制在有效区域,并按照其他人的建议执行 GL_CLAMP_TO_EDGE。

一个更棘手的方法是设置 GL_NEAREST 然后在着色器中自己编写线性采样,使用tex 加上一些偏移量对纹理进行采样(曼哈顿距离应该没问题)并在混合时跳过空颜色(跳过部分是什么您的原始概念中缺少)。棘手的部分是正确设置偏移量。

【讨论】:

  • 可以使用“透明(alpha = 0.0)”作为空颜色,然后预定义的混合功能应该再次起作用。
  • 遗憾的是没有。它充其量只能去除半个纹素宽度的伪影,但空颜色仍会渗入非空纹素,例如左上角纹素的顶部将从红色变为黄色,而 zufry 希望它变为蓝色到边界。
  • 对于黑色区域,我将把 alpha = 0 放在那里。我用黑色显示它,以便在这里更容易解释。还有黑色区域的高度= 0,它进入这些if (color == 0.0f) {base = vec3(0.0f, 0.0f, 0.0f);}。 @Andreas:所以最后它是 GL_LINEAR 的限制?您能提供有关您建议的方法的阅读材料吗?
  • @zufryy 这不是我以前知道的方法。如果您想阅读一些内容,请查看 GL_LINEAR 和 GL_NEAREST 的文档。确保您了解为什么会得到错误的图像输出,并尝试从那里找出满足您要求的算法。祝你好运。
  • @Andreas:问题是当像素尝试计算插值并且相邻像素中存在零点时使用GL_LINEAR时会出现这种情况。因此,我只是将“虚拟”点作为外部边界,然后在那里应用 alpha = 0。
【解决方案3】:

我设法通过使用最近像素的插值值制作外边界并为此设置 alpha = 0 来修复它。

它工作得很好,但是由于我还需要存储 alpha 贴图,它的内存消耗是原始内存消耗的 2 倍。

【讨论】:

  • 请发一张最终结果的图片
  • 边缘有点模糊。但我可以接受。
猜你喜欢
  • 2022-01-21
  • 2020-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 2013-11-10
  • 2017-03-19
相关资源
最近更新 更多