尝试为 opengl 创建像素化着色器失败
Failed attempt to create a pixelating shader for opengl
我正在制作一个基于 libGDX 的游戏,并且我尝试制作一个像素化着色器。对我来说,它看起来应该工作,但它没有。我只在整个屏幕上看到一种颜色的纹理。目标是将详细的纹理变成像素化纹理。
这是我的片段着色器的代码:
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;
}
我想在这里做的是:我得到纹理的大小。然后,使用该尺寸,我 'pixelate' v_texCoord0 并获取该像素的颜色。
一旦我删除了
中的 int
int(v_texCoord0.x * texSize.x) / texSize.x, int(v_texCoord0.y * texSize.y)
,我看到纹理是正常的,否则我看到我在这篇文章开头描述的内容 post。但是,对我来说,我的代码中的任何内容都可能是错误的。
希望有经验的大神帮我解决这个问题!
你在这里做整数除法:
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);
(另请注意,无需单独处理 x
和 y
组件,您可以使用矢量运算。)
但是你在这里做什么并不完全清楚。从概念上讲,您正在模拟 GL_NEAREST
过滤可以免费为您做什么(只是您的选择移动了半个纹素),所以问题是:您从中得到了什么。如果您使用 GL_LINEAR
过滤,上述公式将始终在纹素角处采样,因此线性过滤器将导致平均 2x2 纹素块的颜色。如果你使用 GL_NEAREST
,这个公式不会给你比以前更多的像素化,它只会以一种奇怪的方式移动纹理。如果你使用一些带有 mipmapping 的过滤器,由于方程的非连续性,公式将完全破坏 mipmap 选择(这也会导致 GL 无法以可靠的方式区分纹理缩小或放大,所以它不仅会破坏 mipmapping)。
我正在制作一个基于 libGDX 的游戏,并且我尝试制作一个像素化着色器。对我来说,它看起来应该工作,但它没有。我只在整个屏幕上看到一种颜色的纹理。目标是将详细的纹理变成像素化纹理。 这是我的片段着色器的代码:
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;
}
我想在这里做的是:我得到纹理的大小。然后,使用该尺寸,我 'pixelate' v_texCoord0 并获取该像素的颜色。
一旦我删除了
中的 intint(v_texCoord0.x * texSize.x) / texSize.x, int(v_texCoord0.y * texSize.y)
,我看到纹理是正常的,否则我看到我在这篇文章开头描述的内容 post。但是,对我来说,我的代码中的任何内容都可能是错误的。
希望有经验的大神帮我解决这个问题!
你在这里做整数除法:
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);
(另请注意,无需单独处理 x
和 y
组件,您可以使用矢量运算。)
但是你在这里做什么并不完全清楚。从概念上讲,您正在模拟 GL_NEAREST
过滤可以免费为您做什么(只是您的选择移动了半个纹素),所以问题是:您从中得到了什么。如果您使用 GL_LINEAR
过滤,上述公式将始终在纹素角处采样,因此线性过滤器将导致平均 2x2 纹素块的颜色。如果你使用 GL_NEAREST
,这个公式不会给你比以前更多的像素化,它只会以一种奇怪的方式移动纹理。如果你使用一些带有 mipmapping 的过滤器,由于方程的非连续性,公式将完全破坏 mipmap 选择(这也会导致 GL 无法以可靠的方式区分纹理缩小或放大,所以它不仅会破坏 mipmapping)。