0

I'm making a libGDX based game and I've tried to make a pixelating shader. To me, it looks like it should work but it doesn't. I just see 1 color of the texture all over the screen. The goal was to turn a detailed texture into a pixelated texture. Here is the code of my fragment shader:

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;
}

What I am trying to do here is: I get the size of the texture. Then, with that size, I 'pixelate' v_texCoord0 and get the color of that pixel.

As soon as I remove the int cast in

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

, I see the texture as normal, otherwise I see what I've described in the beginning of this post. However, to me, anything in my code could be wrong.

I hope someone with experience could help me fix this problem!

1
  • If you want the whole screen to be pixelated, this is a convoluted and CPU intensive way to do it. Draw everything normally to a small FrameBuffer and then draw the FrameBuffer's texture to screen. No need for specialized shaders at all. Commented Dec 30, 2017 at 3:10

1 Answer 1

2

You are doing an integer division here:

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

The result can only be an integer, and if v_texCoord0.x is in the range [0,1], it will result in producing zero except for rightmost part of your texture, when the fragment exacly samples at the border of your texture.

You should apply floating-point math to get the effect you want:

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

(Also note that there is no need to work with the x and y components individually, you can use vector operations.)

But what you're doing here is not completely clear. Concenptually, you are emulating what GL_NEAREST filtering can do for you for free (just that your selection is shifted by half a texel), so the question is: what are you getting from this. If you use GL_LINEAR filtering, the above formula will sample always at the texel corners, so that the linear filter will result in averaging the color of a 2x2 texel block. If you use GL_NEAREST, the formula will not give you more pixelation than you had before, it just shifts the texture in a weird way. If you use some filter with mipmapping, the formula will completely break the mipmap selection due to the non-continuous nature of the equation (this will also result in the GL not being able to discern between texture minification or magnification in a reliable way, so it does not break only mipmapping).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.