I’m making a terrain renderer, and I’m using 16bit grayscale pngs as displacement maps. When I load them using THREE.ImageUtils.loadTexture, it works, but I get noticable rounding errors. So I tried to modifiy it like this:

function loadDEM(path, mapping, callback) {
    var image = new Image(), texture = new THREE.Texture(image, mapping);
    texture.type = THREE.UnsignedShortType;
    image.onload = function() {
        texture.needsUpdate = true;
        if (callback) {
    image.crossOrigin = "anonymous";
    image.src = path;
    return texture;

Just added texture.type = THREE.UnsignedShortType, and now I get these errors in console and terrain is flat.

WebGL: INVALID_ENUM: texImage2D: invalid texture type index.html:1
WebGL: INVALID_OPERATION: generateMipmap: level 0 not power of 2 or not all the same size

So how can I use 16bit images?

This is the actual terrain tile:
Terrain tile

Author: Fantashit

1 thought on “THREE.UnsignedShortType

  1. Like all image formats in browsers it’s up to the browser what image formats are supported and what the browser does with them. 😭 For example Chrome and Firefox support webp but Safari does not.

    Also Safari supports (or used to support) TIFF files as <img> tags and it would load and display floating point TIFFs but I’m 99%% it did not support uploading those floating point TIFFs as floating point textures as there is no conformance test for it (not that Apple has ever cared about passing the conformance tests 😂)

    Currently though the WebGL2 spec explicitly disallows 16 int formats from images 🙄

    When the data source is a DOM element (HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement), or is an ImageBitmap, ImageData, or OffscreenCanvas object, commonly each channel’s representation is an unsigned integer type of at least 8 bits. Converting such representation to signed integers or unsigned integers with more bits is not clearly defined. For example, when converting RGBA8 to RGBA16UI, it is unclear whether or not the intention is to scale up values to the full range of a 16-bit unsigned integer. Therefore, only converting to unsigned integer of at most 8 bits, half float, or float is allowed.

Comments are closed.