I'm working on an image processing app which uses WebGL to apply shaders to a bunch of input photos. At one point in the algorithm, I need to create some image pyramids where I downscale the input photos by a factor of two each time, until I reach the smallest possible level.
For my downscaling routine, I'm using a really simple process:
- Create a new, blank texture using
texImage2D
which is half the size of the original. - Attach this texture to a frame buffer and use it as a render target (
bindFrameBuffer
). I also set the viewport to match the new texture's size. - Draw a flat quad whose vertices cover the screen-space coordinates (-1 -> 1) using a 'copy-paste' shader which samples the original (full-size) texture. Note that the texture parameters are always NEAREST and CLAMP_TO_EDGE.
Here's the source code for my fragment shader:
precision mediump float;
uniform sampler2D u_inputImage; // Original full-size texture
varying vec2 v_texCoords;
void main()
{
gl_FragColor = vec4(texture2D(u_inputImage, v_texCoords).rgb, 1);
}
The result looks sensible, but the quality of the downscaled texture is pretty poor. In the following example, you can see how it looks jagged compared to the original, particularly along the edges of the table on the bottom-right. There are also some glitchy pixels on the top of the chair, and under the door handle:
Does anyone know why this simple method doesn't seem to work? Is there a better way of creating a downsampled texture using WebGL/OpenGL?
GL_LINEAR
nearest neighbour is supposed to give blocked artifacts, linear will interpolate hence will look smoother imo? $\endgroup$