GLSL 像素化着色器中的边框伪影

Posted

技术标签:

【中文标题】GLSL 像素化着色器中的边框伪影【英文标题】:Border artefact in GLSL pixelate shader 【发布时间】:2012-07-12 12:43:40 【问题描述】:

我在 GLSL 中做一个简单的像素化着色器。 除了我在像素化边界看到的这个边界伪影之外,一切都按预期工作。

代码是:

precision mediump float;

uniform sampler2D Texture0;
uniform int pixelCount;
varying vec2 fTexCoord;

void main(void)

   float pixelWidth = 1.0/float(pixelCount);

   float x = floor(fTexCoord.x/pixelWidth)*pixelWidth + pixelWidth/2.0;
   float y = floor(fTexCoord.y/pixelWidth)*pixelWidth + pixelWidth/2.0;

   gl_FragColor = texture2D(Texture0, vec2(x, y));

请看附图。

我不知道为什么会这样。 请帮我解决这个问题...

【问题讨论】:

【参考方案1】:

我认为您的问题与纹理插值有关。

您的纹理采样器是否使用GL_NEAREST(这使得纹理采样器使用点采样器而不是一些插值)?

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

此外,您可能不应该使用 mipmap。

了解实际纹理图像的外观以及几何图形的外观也很有用(我假设您正在渲染单个四边形)。

【讨论】:

您对 Mipmap 的看法是正确的。 过滤不是问题。但 mipmap 是。 但我仍然不明白为什么 mipmap 会制作这个人工制品。有人可以解释一下这背后的理论吗? 问题是在生成mipmaps(如gluBuild2DMipmaps)时,该函数使用某种插值来获得好看的缩小图像。但在某些情况下,这不起作用:有时你想保持锐利的边缘(像你一样),有时纹理中的值不是颜色,不能使用线性插值(在这种情况下,纹理存储法线贴图) .在这些情况下,您必须手动生成 mipmap 级别(或根本不使用 mipmap)。 感谢 Mortennobel。 我好奇的心还是有疑问。 如果是因为从 mipmap 过滤了纹素,那么为什么工件仅限于边界。一个 mipmap 级别应该为某个连续区域上的像素提供服务,直到纹素足够小以用于下一个级别的 mipmap;对吗? 我仍然想知道您的屏幕截图是否只包含一个四边形或 9 个四边形?另外我假设您的纹理只有 RGB 而不是 RGBA(具有 alpha 值)。 回答你的最后一个问题:是的,mipmapping 提供最近的 mipmap 级别的像素值(或在两个最近的 mipmap 级别之间进行插值)。无论如何,请查看以下链接 - 这可能会对您有所帮助:opengl.org/wiki/Common_Mistakes#Creating_a_Texture 和 opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation

以上是关于GLSL 像素化着色器中的边框伪影的主要内容,如果未能解决你的问题,请参考以下文章

GLSL:使用片段着色器进行对象翻译

满足条件时是不是可以在 GLSL 着色器中回调 C/C++ 函数/代码? [关闭]

为啥我的着色器中的 GLSL 纹理坐标不是线性的?

顶点纹理获取(在顶点着色器中读取纹理)

从 GLSL 着色器中获取常量

在 GLSL 着色器中访问 VBO/VAO 数据