DEV Community

Cover image for WebGL Month. Day 25. Mipmaps
Andrei Lesnitsky
Andrei Lesnitsky

Posted on

1 1

WebGL Month. Day 25. Mipmaps

This is a series of blog posts related to WebGL. New post will be available every day

GitHub stars
Twitter Follow

Join mailing list to get new posts right to your inbox

Source code available here

Built with

Git Tutor Logo


Hey πŸ‘‹

Welcome to WebGL month

Today we're going to learn one more webgl concept which might improve the quality of the final rendered image

First we need to discuss how color is being read from texture.

Let say we have a 1024x1024 image, but render only a 512x512 area on canvas. So each pixel in resulting image represents 4 pixels in original texture.

Here's where gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter) plays some role

There are several algorithms on how to read a color from the texture

  • gl.LINEAR - this one will read 4 pixels of original image and blend colors of 4 pixels to calculate final pixel color

  • gl.NEARETS will just take the closest coordinate of the pixel from original image and use this color. While being more performant, this method has a lower quality

Both methods has it's caveats, especially when the size of area which need to be painted with texture is much smaller than original texture

There is a special technique which allows to improve the quality and performance of rendering when dealing with textures. This special textures are called [mipmaps] – pre-calculated sequences of images, where each next image has a progressively smaller resolution. So when fragment shader reads a color from a texture, it takes the closest texture in size, and reads a color from it.

In WebGL 1.0 mipmaps can only be generated for textures of "power-of-2" size (256x256, 512x512, 1024x1024 etc.)

And that's how mipmap will look like for our dirt cube

Mipmap

Don't worry, you don't need to generate such a sequence for all your textures, this could be done automatically if your texture is a size of power of 2

πŸ“„ src/minecraft-terrain.js


  const State = {};

+ /**
+  *
+  * @param {WebGLRenderingContext} gl
+  */
  export async function prepare(gl) {
      const vShader = gl.createShader(gl.VERTEX_SHADER);
      const fShader = gl.createShader(gl.FRAGMENT_SHADER);
      await loadImage(textureSource).then((image) => {
          const texture = createTexture(gl);
          setImage(gl, texture, image);
+ 
+         gl.generateMipmap(gl.TEXTURE_2D);
      });

      setupAttributes(gl);

Enter fullscreen mode Exit fullscreen mode

And in order to make GPU read a pixel color from mipmap, we need to specify TEXTURE_MIN_FILTER.

πŸ“„ src/minecraft-terrain.js

          setImage(gl, texture, image);

          gl.generateMipmap(gl.TEXTURE_2D);
+         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_LINEAR);
      });

      setupAttributes(gl);

Enter fullscreen mode Exit fullscreen mode

NEAREST_MIPMAP_LINEAR will choose the closest size mipmap and interpolate 4 pixels to get resulting color

That's it for today!

Thanks for reading, see you tomorrow πŸ‘‹


GitHub stars
Twitter Follow

Join mailing list to get new posts right to your inbox

Source code available here

Built with

Git Tutor Logo

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

πŸ‘₯ Ideal for solo developers, teams, and cross-company projects

Learn more

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay