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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了尝试为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;
}

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

一旦我删除了int cast

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)。

以上是关于尝试为opengl创建像素化着色器失败的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL片段着色器不照亮场景

纹理中的 OpenGL 片段着色器

✠OpenGL-2-图像管线

OpenGL、GLSL 片段着色器无法读取 Sampler2D 纹理

OpenGLES3.0创建着色器步骤

OpenGL中着色器,渲染管线,光栅化