尝试为 opengl 创建像素化着色器失败



我正在制作一个基于libGDX的游戏,我试图制作一个像素化的着色器。对我来说,它看起来应该有效,但事实并非如此。我只在屏幕上看到 1 种颜色的纹理。目标是将详细的纹理转换为像素化的纹理。 这是我的片段着色器的代码:

precision mediump float;
varying vec4 v_color;
varying vec2 v_texCoord0;
uniform sampler2D u_sampler2D;
void main(){
ivec2 texSize = textureSize( u_sampler2D, 0);
vec4 color = texture2D(u_sampler2D, vec2(int(v_texCoord0.x * texSize.x) / texSize.x, int(v_texCoord0.y * texSize.y) / texSize.y)) * v_color;
gl_FragColor = color;
}

我在这里要做的是:我得到纹理的大小。然后,用这个大小,我v_texCoord0"像素化"并获得该像素的颜色。

一旦我删除了 int 铸件

int(v_texCoord0.x * texSize.x) / texSize.x, int(v_texCoord0.y * texSize.y)

,我认为纹理正常,否则我会看到我在本文开头描述的内容。但是,对我来说,我的代码中的任何内容都可能是错误的。

我希望有经验的人可以帮助我解决这个问题!

您在这里进行整数除法:

ivec2 texSize;
[...] int(v_texCoord0.x * texSize.x) / texSize.x

结果只能是一个整数,如果v_texCoord0.x在 [0,1] 范围内,则当片段在纹理的边界处精确采样时,将导致除纹理的最右侧部分外,生成零。

您应该应用浮点数学来获得所需的效果:

vec2 texSize=vec2(textureSize( u_sampler2D, 0));
vec4 color = texture2D(u_sampler2D, floor(v_texCoord0 * texSize) / texSize);

(另请注意,无需单独处理xy组件,您可以使用矢量运算。

但是你在这里做什么并不完全清楚。简而言之,您正在模拟GL_NEAREST过滤可以免费为您做的事情(只是您的选择移动了半个纹素),所以问题是:您从中得到了什么。如果使用GL_LINEAR过滤,则上述公式将始终在纹素角处采样,因此线性滤波器将产生平均 2x2 纹素块的颜色。如果你使用GL_NEAREST,该公式不会给你比以前更多的像素化,它只是以一种奇怪的方式改变纹理。如果你使用一些带有 mipmapping 的过滤器,由于方程的非连续性,公式将完全破坏 mipmap 选择(这也将导致 GL 无法以可靠的方式区分纹理缩小或放大,因此它不会只破坏 mipmapping)。

最新更新